mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-09 15:45:40 +12:00
[GL renderer] Implement clipping planes
This commit is contained in:
parent
f7ad66c708
commit
aa27389473
1 changed files with 64 additions and 21 deletions
|
@ -30,14 +30,16 @@ const char* vertexShader = R"(
|
|||
flat out vec4 v_textureEnvColor[6];
|
||||
flat out vec4 v_textureEnvBufferColor;
|
||||
|
||||
out float gl_ClipDistance[2];
|
||||
|
||||
// TEV uniforms
|
||||
uniform uint u_textureEnvColor[6];
|
||||
uniform uint u_textureEnvBufferColor;
|
||||
uniform uint u_picaRegs[0x200-0x47];
|
||||
uniform uint u_picaRegs[0x200 - 0x47];
|
||||
|
||||
//Helper so that the implementation of u_pica_regs can be changed later
|
||||
// Helper so that the implementation of u_pica_regs can be changed later
|
||||
uint readPicaReg(uint reg_addr){
|
||||
return u_picaRegs[reg_addr-0x47];
|
||||
return u_picaRegs[reg_addr - 0x47];
|
||||
}
|
||||
|
||||
vec4 abgr8888ToVec4(uint abgr) {
|
||||
|
@ -50,10 +52,30 @@ const char* vertexShader = R"(
|
|||
float(abgr >> 24)
|
||||
);
|
||||
}
|
||||
|
||||
vec3 rotateVec3ByQuaternion(vec3 v, vec4 q){
|
||||
vec3 u=q.xyz;
|
||||
vec3 u = q.xyz;
|
||||
float s = q.w;
|
||||
return 2.0*dot(u, v)*u + (s*s - dot(u, u))*v + 2.0*s*cross(u, v);
|
||||
return 2.0 * dot(u, v) * u + (s * s - dot(u, u))* v + 2.0 * s * cross(u, v);
|
||||
}
|
||||
|
||||
// Convert an arbitrary-width floating point literal to an f32
|
||||
float decodeFP(uint hex, uint E, uint M){
|
||||
uint width = M + E + 1u;
|
||||
uint bias = 128u - (1u << (E - 1u));
|
||||
uint exponent = (hex >> M) & ((1u << E) - 1u);
|
||||
uint mantissa = hex & ((1u << M) - 1u);
|
||||
uint sign = (hex >> (E + M)) << 31u;
|
||||
|
||||
if ((hex & ((1u << (width - 1u)) - 1u)) != 0) {
|
||||
if (exponent == (1u << E) - 1u) exponent = 255u;
|
||||
else exponent += bias;
|
||||
hex = sign | (mantissa << (23u - M)) | (exponent << 23u);
|
||||
} else {
|
||||
hex = sign;
|
||||
}
|
||||
|
||||
return uintBitsToFloat(hex);
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
@ -66,15 +88,30 @@ const char* vertexShader = R"(
|
|||
v_texcoord2 = vec2(a_texcoord2.x, 1.0 - a_texcoord2.y);
|
||||
v_view = a_view;
|
||||
|
||||
v_normal = normalize(rotateVec3ByQuaternion(vec3(0.0,0.0,1.0), a_quaternion));
|
||||
v_tangent = normalize(rotateVec3ByQuaternion(vec3(1.0,0.0,0.0), a_quaternion));
|
||||
v_bitangent = normalize(rotateVec3ByQuaternion(vec3(0.0,1.0,0.0), a_quaternion));
|
||||
v_normal = normalize(rotateVec3ByQuaternion(vec3(0.0, 0.0, 1.0), a_quaternion));
|
||||
v_tangent = normalize(rotateVec3ByQuaternion(vec3(1.0, 0.0, 0.0), a_quaternion));
|
||||
v_bitangent = normalize(rotateVec3ByQuaternion(vec3(0.0, 1.0, 0.0), a_quaternion));
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
v_textureEnvColor[i] = abgr8888ToVec4(u_textureEnvColor[i]);
|
||||
}
|
||||
|
||||
v_textureEnvBufferColor = abgr8888ToVec4(u_textureEnvBufferColor);
|
||||
|
||||
// Parse clipping plane registers
|
||||
// The plane registers describe a clipping plane in the form of Ax + By + Cz + D = 0
|
||||
// With n = (A, B, C) being the normal vector and D being the origin point distance
|
||||
// Therefore, for the second clipping plane, we can just pass the dot product of the clip vector and the input coordinates to gl_ClipDistance[1]
|
||||
vec4 clipData = vec4(
|
||||
decodeFP(readPicaReg(0x48) & 0xffffffu, 7, 16),
|
||||
decodeFP(readPicaReg(0x49) & 0xffffffu, 7, 16),
|
||||
decodeFP(readPicaReg(0x4A) & 0xffffffu, 7, 16),
|
||||
decodeFP(readPicaReg(0x4B) & 0xffffffu, 7, 16)
|
||||
);
|
||||
|
||||
// There's also another, always-on clipping plane based on vertex z
|
||||
gl_ClipDistance[0] = -a_coords.z;
|
||||
gl_ClipDistance[1] = dot(clipData, a_coords);
|
||||
}
|
||||
)";
|
||||
|
||||
|
@ -114,11 +151,11 @@ const char* fragmentShader = R"(
|
|||
uniform sampler2D u_tex2;
|
||||
uniform sampler1DArray u_tex_lighting_lut;
|
||||
|
||||
uniform uint u_picaRegs[0x200-0x47];
|
||||
uniform uint u_picaRegs[0x200 - 0x47];
|
||||
|
||||
//Helper so that the implementation of u_pica_regs can be changed later
|
||||
// Helper so that the implementation of u_pica_regs can be changed later
|
||||
uint readPicaReg(uint reg_addr){
|
||||
return u_picaRegs[reg_addr-0x47];
|
||||
return u_picaRegs[reg_addr - 0x47];
|
||||
}
|
||||
|
||||
vec4 tevSources[16];
|
||||
|
@ -233,9 +270,9 @@ const char* fragmentShader = R"(
|
|||
|
||||
float lutLookup(uint lut, uint light, float value){
|
||||
if (lut >= FR_LUT && lut <= RR_LUT)
|
||||
lut-=1;
|
||||
lut -= 1;
|
||||
if (lut==SP_LUT)
|
||||
lut=8+light;
|
||||
lut = light + 8;
|
||||
return texture(u_tex_lighting_lut, vec2(value, lut)).r;
|
||||
}
|
||||
|
||||
|
@ -303,12 +340,12 @@ const char* fragmentShader = R"(
|
|||
|
||||
bool error_unimpl = false;
|
||||
|
||||
for(uint i = 0; i < GPUREG_LIGHTING_NUM_LIGHTS; i++){
|
||||
for (uint i = 0; i < GPUREG_LIGHTING_NUM_LIGHTS; i++){
|
||||
uint light_id = bitfieldExtract(GPUREG_LIGHTING_LIGHT_PERMUTATION,int(i*3),3);
|
||||
|
||||
uint GPUREG_LIGHTi_SPECULAR0 = readPicaReg(0x0140 + 0x10 * light_id);
|
||||
uint GPUREG_LIGHTi_SPECULAR1 = readPicaReg(0x0141 + 0x10 * light_id);
|
||||
uint GPUREG_LIGHTi_DIFFUSE = readPicaReg(0x0142 +0x10 * light_id);
|
||||
uint GPUREG_LIGHTi_DIFFUSE = readPicaReg(0x0142 + 0x10 * light_id);
|
||||
uint GPUREG_LIGHTi_AMBIENT = readPicaReg(0x0143 + 0x10 * light_id);
|
||||
uint GPUREG_LIGHTi_VECTOR_LOW = readPicaReg(0x0144 + 0x10 * light_id);
|
||||
uint GPUREG_LIGHTi_VECTOR_HIGH= readPicaReg(0x0145 + 0x10 * light_id);
|
||||
|
@ -334,11 +371,11 @@ const char* fragmentShader = R"(
|
|||
scale/=256.0;
|
||||
|
||||
uint input_id = bitfieldExtract(GPUREG_LIGHTING_LUTINPUT_SELECT, c * 4, 3);
|
||||
if (input_id==0u) d[c] = dot(normal,half_vector);
|
||||
else if (input_id==1u) d[c] = dot(view,half_vector);
|
||||
else if (input_id==2u) d[c] = dot(normal,view);
|
||||
else if (input_id==3u) d[c] = dot(light_vector,normal);
|
||||
else if (input_id==4u){
|
||||
if (input_id == 0u) d[c] = dot(normal,half_vector);
|
||||
else if (input_id == 1u) d[c] = dot(view,half_vector);
|
||||
else if (input_id == 2u) d[c] = dot(normal,view);
|
||||
else if (input_id == 3u) d[c] = dot(light_vector,normal);
|
||||
else if (input_id == 4u){
|
||||
uint GPUREG_LIGHTi_SPOTDIR_LOW = readPicaReg(0x0146 + 0x10 * light_id);
|
||||
uint GPUREG_LIGHTi_SPOTDIR_HIGH= readPicaReg(0x0147 + 0x10 * light_id);
|
||||
vec3 spot_light_vector = normalize(vec3(
|
||||
|
@ -828,6 +865,11 @@ void Renderer::drawVertices(PICA::PrimType primType, std::span<const PicaVertex>
|
|||
glUniform1ui(alphaControlLoc, alphaControl);
|
||||
}
|
||||
|
||||
OpenGL::enableClipPlane(0); // Clipping plane 0 is always enabled
|
||||
if (regs[PICA::InternalRegs::ClipEnable] & 1) {
|
||||
OpenGL::enableClipPlane(1);
|
||||
}
|
||||
|
||||
setupBlending();
|
||||
OpenGL::Framebuffer poop = getColourFBO();
|
||||
poop.bind(OpenGL::DrawAndReadFramebuffer);
|
||||
|
@ -904,7 +946,6 @@ void Renderer::drawVertices(PICA::PrimType primType, std::span<const PicaVertex>
|
|||
constexpr u32 topScreenBuffer = 0x1f000000;
|
||||
constexpr u32 bottomScreenBuffer = 0x1f05dc00;
|
||||
|
||||
// Quick hack to display top screen for now
|
||||
void Renderer::display() {
|
||||
OpenGL::disableScissor();
|
||||
|
||||
|
@ -1000,6 +1041,8 @@ void Renderer::displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32
|
|||
OpenGL::disableBlend();
|
||||
OpenGL::disableDepth();
|
||||
OpenGL::disableScissor();
|
||||
OpenGL::disableClipPlane(0);
|
||||
OpenGL::disableClipPlane(1);
|
||||
displayProgram.use();
|
||||
|
||||
// Hack: Detect whether we are writing to the top or bottom screen by checking output gap and drawing to the proper part of the output texture
|
||||
|
|
Loading…
Add table
Reference in a new issue