mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-06 06:05:40 +12:00
[GPU] Start texture combiner implementation
This commit first implements experimental and incomplete texture combiner support. Currently only the first texture combiner is implemented. Many sources and combine modes are not implemented yet.
This commit is contained in:
parent
18776702e0
commit
4322ebda2c
3 changed files with 135 additions and 15 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -8,6 +8,7 @@
|
|||
|
||||
#Clion Files
|
||||
.idea/
|
||||
cmake-build-*
|
||||
|
||||
Debug/
|
||||
Release/
|
||||
|
|
|
@ -24,7 +24,14 @@ class Renderer {
|
|||
OpenGL::VertexBuffer vbo;
|
||||
GLint alphaControlLoc = -1;
|
||||
GLint texUnitConfigLoc = -1;
|
||||
|
||||
|
||||
// TEV configuration uniform locations
|
||||
GLint textureEnv0SourceLoc = -1;
|
||||
GLint textureEnv0OperandLoc = -1;
|
||||
GLint textureEnv0CombinerLoc = -1;
|
||||
GLint textureEnv0ColorLoc = -1;
|
||||
GLint textureEnv0ScaleLoc = -1;
|
||||
|
||||
// Depth configuration uniform locations
|
||||
GLint depthOffsetLoc = -1;
|
||||
GLint depthScaleLoc = -1;
|
||||
|
|
|
@ -38,6 +38,14 @@ const char* fragmentShader = R"(
|
|||
uniform uint u_alphaControl;
|
||||
uniform uint u_textureConfig;
|
||||
|
||||
// TEV uniforms
|
||||
// TODO: use arrays to handle TEVs 1-3.
|
||||
uniform uint u_textureEnv0Source;
|
||||
uniform uint u_textureEnv0Operand;
|
||||
uniform uint u_textureEnv0Combiner;
|
||||
uniform vec4 u_textureEnv0Color; // TODO: -> Colour
|
||||
uniform uint u_textureEnv0Scale;
|
||||
|
||||
// Depth control uniforms
|
||||
uniform float u_depthScale;
|
||||
uniform float u_depthOffset;
|
||||
|
@ -45,6 +53,88 @@ const char* fragmentShader = R"(
|
|||
|
||||
uniform sampler2D u_tex0;
|
||||
|
||||
vec4 tev_evaluate_source(int src_id) {
|
||||
vec4 source = vec4(1.0);
|
||||
|
||||
uint rgb_source = (u_textureEnv0Source >> (src_id * 4)) & 15u;
|
||||
uint alpha_source = (u_textureEnv0Source >> (16 + src_id * 4)) & 15u;
|
||||
|
||||
// TODO: get rid of redundant texture fetches during TEV evaluation.
|
||||
|
||||
switch (rgb_source) {
|
||||
case 0u: source.rgb = colour.rgb; break; // Primary color, TODO: confirm that this is correct
|
||||
case 3u: source.rgb = texture(u_tex0, tex0_UVs).rgb; break; // Texture 0
|
||||
case 14u: source.rgb = u_textureEnv0Color.rgb; break; // Constant (GPUREG_TEXENVi_COLOR)
|
||||
default: break; // TODO: implement remaining sources
|
||||
}
|
||||
|
||||
switch (alpha_source) {
|
||||
case 0u: source.a = colour.a; break; // Primary color, TODO: confirm that this is correct
|
||||
case 3u: source.a = texture(u_tex0, tex0_UVs).a; break; // Texture 0
|
||||
case 14u: source.a = u_textureEnv0Color.a; break; // Constant (GPUREG_TEXENVi_COLOR)
|
||||
default: break; // TODO: implement remaining sources
|
||||
}
|
||||
|
||||
uint rgb_operand = (u_textureEnv0Operand >> (src_id * 4)) & 15u;
|
||||
uint alpha_operand = (u_textureEnv0Operand >> (12 + src_id * 4)) & 7u;
|
||||
|
||||
vec4 final;
|
||||
|
||||
switch (rgb_operand) {
|
||||
case 0u: final.rgb = source.rgb; break; // Source color
|
||||
case 1u: final.rgb = 1.0 - source.rgb; break; // One minus source color
|
||||
case 2u: final.rgb = vec3(source.a); break; // Source alpha
|
||||
case 3u: final.rgb = vec3(1.0 - source.a); break; // One minus source alpha
|
||||
case 4u: final.rgb = vec3(source.r); break; // Source red
|
||||
case 5u: final.rgb = vec3(1.0 - source.r); break; // One minus source red
|
||||
case 8u: final.rgb = vec3(source.g); break; // Source green
|
||||
case 9u: final.rgb = vec3(1.0 - source.g); break; // One minus source green
|
||||
case 12u: final.rgb = vec3(source.b); break; // Source blue
|
||||
case 13u: final.rgb = vec3(1.0 - source.b); break; // One minus source blue
|
||||
default: break; // TODO: figure out what the undocumented values do
|
||||
}
|
||||
|
||||
switch (alpha_operand) {
|
||||
case 0u: final.a = source.a; break; // Source alpha
|
||||
case 1u: final.a = 1.0 - source.a; break; // One minus source alpha
|
||||
case 2u: final.a = source.r; break; // Source red
|
||||
case 3u: final.a = 1.0 - source.r; break; // One minus source red
|
||||
case 4u: final.a = source.g; break; // Source green
|
||||
case 5u: final.a = 1.0 - source.g; break; // One minus source green
|
||||
case 6u: final.a = source.b; break; // Source blue
|
||||
case 7u: final.a = 1.0 - source.b; break; // One minus source blue
|
||||
}
|
||||
|
||||
// TODO: respect GPUREG_TEXENVi_SCALE
|
||||
|
||||
return final;
|
||||
}
|
||||
|
||||
vec4 tev_combine() {
|
||||
vec4 source0 = tev_evaluate_source(0);
|
||||
vec4 source1 = tev_evaluate_source(1);
|
||||
vec4 source2 = tev_evaluate_source(2);
|
||||
|
||||
uint rgb_combine = u_textureEnv0Combiner & 15u;
|
||||
uint alpha_combine = (u_textureEnv0Combiner >> 16) & 15u;
|
||||
|
||||
vec4 result = vec4(1.0);
|
||||
|
||||
// TODO: figure out how most of the combine modes work.
|
||||
|
||||
switch (rgb_combine) {
|
||||
case 1u: result.rgb = source0.rgb * source1.rgb * source2.rgb; break; // Modulate
|
||||
default: return vec4(1.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
switch (alpha_combine) {
|
||||
case 1u: result.a = source0.a * source1.a * source2.a; break; // Modulate
|
||||
default: return vec4(1.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void main() {
|
||||
if ((u_textureConfig & 1u) != 0) { // Render texture 0 if enabled
|
||||
fragColour = texture(u_tex0, tex0_UVs);
|
||||
|
@ -70,28 +160,28 @@ const char* fragmentShader = R"(
|
|||
|
||||
switch (func) {
|
||||
case 0: discard; // Never pass alpha test
|
||||
case 1: break; // Always pass alpha test
|
||||
case 2: // Pass if equal
|
||||
case 1: break; // Always pass alpha test
|
||||
case 2: // Pass if equal
|
||||
if (alpha != reference)
|
||||
discard;
|
||||
break;
|
||||
case 3: // Pass if not equal
|
||||
case 3: // Pass if not equal
|
||||
if (alpha == reference)
|
||||
discard;
|
||||
break;
|
||||
case 4: // Pass if less than
|
||||
case 4: // Pass if less than
|
||||
if (alpha >= reference)
|
||||
discard;
|
||||
break;
|
||||
case 5: // Pass if less than or equal
|
||||
case 5: // Pass if less than or equal
|
||||
if (alpha > reference)
|
||||
discard;
|
||||
break;
|
||||
case 6: // Pass if greater than
|
||||
case 6: // Pass if greater than
|
||||
if (alpha <= reference)
|
||||
discard;
|
||||
break;
|
||||
case 7: // Pass if greater than or equal
|
||||
case 7: // Pass if greater than or equal
|
||||
if (alpha < reference)
|
||||
discard;
|
||||
break;
|
||||
|
@ -106,11 +196,11 @@ const char* displayVertexShader = R"(
|
|||
|
||||
void main() {
|
||||
const vec4 positions[4] = vec4[](
|
||||
vec4(-1.0, 1.0, 1.0, 1.0), // Top-left
|
||||
vec4(1.0, 1.0, 1.0, 1.0), // Top-right
|
||||
vec4(-1.0, -1.0, 1.0, 1.0), // Bottom-left
|
||||
vec4(1.0, -1.0, 1.0, 1.0) // Bottom-right
|
||||
);
|
||||
vec4(-1.0, 1.0, 1.0, 1.0), // Top-left
|
||||
vec4(1.0, 1.0, 1.0, 1.0), // Top-right
|
||||
vec4(-1.0, -1.0, 1.0, 1.0), // Bottom-left
|
||||
vec4(1.0, -1.0, 1.0, 1.0) // Bottom-right
|
||||
);
|
||||
|
||||
// The 3DS displays both screens' framebuffer rotated 90 deg counter clockwise
|
||||
// So we adjust our texcoords accordingly
|
||||
|
@ -119,10 +209,10 @@ const char* displayVertexShader = R"(
|
|||
vec2(1.0, 0.0), // Bottom-right
|
||||
vec2(0.0, 1.0), // Top-left
|
||||
vec2(0.0, 0.0) // Bottom-left
|
||||
);
|
||||
);
|
||||
|
||||
gl_Position = positions[gl_VertexID];
|
||||
UV = texcoords[gl_VertexID];
|
||||
UV = texcoords[gl_VertexID];
|
||||
}
|
||||
)";
|
||||
|
||||
|
@ -179,6 +269,12 @@ void Renderer::initGraphicsContext() {
|
|||
alphaControlLoc = OpenGL::uniformLocation(triangleProgram, "u_alphaControl");
|
||||
texUnitConfigLoc = OpenGL::uniformLocation(triangleProgram, "u_textureConfig");
|
||||
|
||||
textureEnv0SourceLoc = OpenGL::uniformLocation(triangleProgram, "u_textureEnv0Source");
|
||||
textureEnv0OperandLoc = OpenGL::uniformLocation(triangleProgram, "u_textureEnv0Operand");
|
||||
textureEnv0CombinerLoc = OpenGL::uniformLocation(triangleProgram, "u_textureEnv0Combiner");
|
||||
textureEnv0ColorLoc = OpenGL::uniformLocation(triangleProgram, "u_textureEnv0Color");
|
||||
textureEnv0ScaleLoc = OpenGL::uniformLocation(triangleProgram, "u_textureEnv0Scale");
|
||||
|
||||
depthScaleLoc = OpenGL::uniformLocation(triangleProgram, "u_depthScale");
|
||||
depthOffsetLoc = OpenGL::uniformLocation(triangleProgram, "u_depthOffset");
|
||||
depthmapEnableLoc = OpenGL::uniformLocation(triangleProgram, "u_depthmapEnable");
|
||||
|
@ -331,6 +427,22 @@ void Renderer::drawVertices(OpenGL::Primitives primType, Vertex* vertices, u32 c
|
|||
glUniform1i(depthmapEnableLoc, depthMapEnable);
|
||||
}
|
||||
|
||||
// TODO: only update TEV uniforms when the configuration changes.
|
||||
// TODO: define registers in the PICAInternalRegs enumeration
|
||||
glUniform1ui(textureEnv0SourceLoc, regs[0xc0]);
|
||||
glUniform1ui(textureEnv0OperandLoc, regs[0xc1]);
|
||||
glUniform1ui(textureEnv0CombinerLoc, regs[0xc2]);
|
||||
{
|
||||
const u32 rgba = regs[0xc3];
|
||||
const float r = (float)(rgba & 0xff) / 255.0f;
|
||||
const float g = (float)((rgba >> 8) & 0xff) / 255.0f;
|
||||
const float b = (float)((rgba >> 16) & 0xff) / 255.0f;
|
||||
const float a = (float)(rgba >> 24) / 255.0f;
|
||||
|
||||
glUniform4f(textureEnv0ColorLoc, r, g, b, a);
|
||||
}
|
||||
glUniform1ui(textureEnv0ScaleLoc, regs[0xc4]);
|
||||
|
||||
// Hack for rendering texture 1
|
||||
if (regs[0x80] & 1) {
|
||||
const u32 dim = regs[0x82];
|
||||
|
|
Loading…
Add table
Reference in a new issue