diff --git a/GPU/GLES/FragmentShaderGenerator.cpp b/GPU/GLES/FragmentShaderGenerator.cpp index 57876b939..16613d10c 100644 --- a/GPU/GLES/FragmentShaderGenerator.cpp +++ b/GPU/GLES/FragmentShaderGenerator.cpp @@ -85,6 +85,7 @@ void ComputeFragmentShaderID(FragmentShaderID *id) { bool enableAlphaTest = gstate.isAlphaTestEnabled() && !IsAlphaTestTriviallyTrue(); bool enableColorTest = gstate.isColorTestEnabled() && !IsColorTestTriviallyTrue(); int lmode = (gstate.lmode & 1) && gstate.isLightingEnabled(); + bool doTextureProjection = gstate.getUVGenMode() == 1; // id->d[0] |= (gstate.clearmode & 1); if (gstate.isTextureMapEnabled()) { @@ -101,6 +102,7 @@ void ComputeFragmentShaderID(FragmentShaderID *id) { if (enableColorTest) id->d[0] |= (gstate.colortest & 0x3) << 13; // color test func id->d[0] |= (enableFog & 1) << 15; + id->d[0] |= (doTextureProjection & 1) << 16; } } @@ -117,11 +119,11 @@ void GenerateFragmentShader(char *buffer) { int lmode = (gstate.lmode & 1) && gstate.isLightingEnabled(); int doTexture = gstate.isTextureMapEnabled() && !gstate.isModeClear(); - bool enableFog = gstate.isFogEnabled() && !gstate.isModeThrough() && !gstate.isModeClear(); bool enableAlphaTest = gstate.isAlphaTestEnabled() && !IsAlphaTestTriviallyTrue() && !gstate.isModeClear(); bool enableColorTest = gstate.isColorTestEnabled() && !IsColorTestTriviallyTrue() && !gstate.isModeClear(); bool enableColorDoubling = (gstate.texfunc & 0x10000) != 0; + bool doTextureProjection = gstate.getUVGenMode() == 1; if (doTexture) WRITE(p, "uniform sampler2D tex;\n"); @@ -145,7 +147,12 @@ void GenerateFragmentShader(char *buffer) { #endif } if (doTexture) - WRITE(p, "varying vec2 v_texcoord;\n"); + { + if (doTextureProjection) + WRITE(p, "varying vec3 v_texcoord;\n"); + else + WRITE(p, "varying vec2 v_texcoord;\n"); + } WRITE(p, "void main() {\n"); @@ -163,7 +170,11 @@ void GenerateFragmentShader(char *buffer) { } if (gstate.textureMapEnable & 1) { - WRITE(p, " vec4 t = texture2D(tex, v_texcoord);\n"); + if (doTextureProjection) { + WRITE(p, " vec4 t = texture2DProj(tex, v_texcoord);\n"); + } else { + WRITE(p, " vec4 t = texture2D(tex, v_texcoord);\n"); + } WRITE(p, " vec4 p = v_color0;\n"); if (gstate.texfunc & 0x100) { // texfmt == RGBA @@ -234,7 +245,7 @@ void GenerateFragmentShader(char *buffer) { #ifdef DEBUG_SHADER if (doTexture) { - WRITE(p, " gl_FragColor = texture2D(tex, v_texcoord);\n"); + WRITE(p, " gl_FragColor = texture2D(tex, v_texcoord.xy);\n"); } else { WRITE(p, " gl_FragColor = vec4(1,0,1,1);\n"); } diff --git a/GPU/GLES/ShaderManager.cpp b/GPU/GLES/ShaderManager.cpp index 76cc331c7..1a3579e67 100644 --- a/GPU/GLES/ShaderManager.cpp +++ b/GPU/GLES/ShaderManager.cpp @@ -77,6 +77,11 @@ LinkedShader::LinkedShader(Shader *vs, Shader *fs) ERROR_LOG(G3D, "Could not link program:\n %s", buf); ERROR_LOG(G3D, "VS:\n%s", vs->source().c_str()); ERROR_LOG(G3D, "FS:\n%s", fs->source().c_str()); +#ifdef SHADERLOG + OutputDebugString(buf); + OutputDebugString(vs->source().c_str()); + OutputDebugString(fs->source().c_str()); +#endif delete [] buf; // we're dead! } return; diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index a571c93e2..b8f5f7009 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -486,7 +486,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw( float v[3] = {0, 0, 0}; float c0[4] = {1, 1, 1, 1}; float c1[4] = {0, 0, 0, 0}; - float uv[2] = {0, 0}; + float uv[3] = {0, 0, 0}; float fogCoef = 1.0f; if (throughmode) { @@ -615,6 +615,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw( // Texture scale/offset is only performed in this mode. uv[0] = uscale * (ruv[0]*gstate_c.uScale + gstate_c.uOff); uv[1] = vscale * (ruv[1]*gstate_c.vScale + gstate_c.vOff); + uv[2] = 1.0f; break; case 1: { @@ -640,6 +641,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw( Vec3ByMatrix43(uvw, &source.x, gstate.tgenMatrix); uv[0] = uvw[0]; uv[1] = uvw[1]; + uv[2] = uvw[2]; } break; case 2: @@ -650,6 +652,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw( uv[0] = (1.0f + (lightpos0 * normal))/2.0f; uv[1] = (1.0f - (lightpos1 * normal))/2.0f; + uv[2] = 1.0f; } break; case 3: @@ -665,7 +668,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw( // TODO: Write to a flexible buffer, we don't always need all four components. memcpy(&transformed[index].x, v, 3 * sizeof(float)); transformed[index].fog = fogCoef; - memcpy(&transformed[index].u, uv, 2 * sizeof(float)); + memcpy(&transformed[index].u, uv, 3 * sizeof(float)); if (gstate_c.flipTexture) { if (throughmode) transformed[index].v = 1.0f - transformed[index].v; @@ -763,11 +766,12 @@ void TransformDrawEngine::SoftwareTransformAndDraw( glBindBuffer(GL_ARRAY_BUFFER, vbo_[curVbo_]); glBufferData(GL_ARRAY_BUFFER, vertexSize * numTrans, drawBuffer, GL_STREAM_DRAW); drawBuffer = 0; // so that the calls use offsets instead. - } + } + bool doTextureProjection = gstate.getUVGenMode() == 1; glVertexAttribPointer(program->a_position, 4, GL_FLOAT, GL_FALSE, vertexSize, drawBuffer); - if (program->a_texcoord != -1) glVertexAttribPointer(program->a_texcoord, 2, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 4 * 4); - if (program->a_color0 != -1) glVertexAttribPointer(program->a_color0, 4, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, ((uint8_t*)drawBuffer) + 6 * 4); - if (program->a_color1 != -1) glVertexAttribPointer(program->a_color1, 3, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, ((uint8_t*)drawBuffer) + 7 * 4); + if (program->a_texcoord != -1) glVertexAttribPointer(program->a_texcoord, doTextureProjection ? 3 : 2, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 4 * 4); + if (program->a_color0 != -1) glVertexAttribPointer(program->a_color0, 4, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, ((uint8_t*)drawBuffer) + 7 * 4); + if (program->a_color1 != -1) glVertexAttribPointer(program->a_color1, 3, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, ((uint8_t*)drawBuffer) + 8 * 4); if (drawIndexed) { if (useVBO) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_[curVbo_]); diff --git a/GPU/GLES/VertexDecoder.h b/GPU/GLES/VertexDecoder.h index 9a40c8a77..309e4f336 100644 --- a/GPU/GLES/VertexDecoder.h +++ b/GPU/GLES/VertexDecoder.h @@ -63,7 +63,7 @@ struct DecVtxFormat { struct TransformedVertex { float x, y, z, fog; // in case of morph, preblend during decode - float u; float v; // scaled by uscale, vscale, if there + float u; float v; float w; // scaled by uscale, vscale, if there u8 color0[4]; // prelit u8 color1[3]; // prelit }; diff --git a/GPU/GLES/VertexShaderGenerator.cpp b/GPU/GLES/VertexShaderGenerator.cpp index 81135c70d..dea27ffac 100644 --- a/GPU/GLES/VertexShaderGenerator.cpp +++ b/GPU/GLES/VertexShaderGenerator.cpp @@ -45,6 +45,7 @@ bool CanUseHardwareTransform(int prim) { // prim so we can special case for RECTANGLES :( void ComputeVertexShaderID(VertexShaderID *id, int prim) { int doTexture = gstate.isTextureMapEnabled() && !gstate.isModeClear(); + bool doTextureProjection = gstate.getUVGenMode() == 1; bool hasColor = (gstate.vertType & GE_VTYPE_COL_MASK) != 0; bool hasNormal = (gstate.vertType & GE_VTYPE_NRM_MASK) != 0; @@ -59,7 +60,10 @@ void ComputeVertexShaderID(VertexShaderID *id, int prim) { id->d[0] |= doTexture << 3; id->d[0] |= (hasColor & 1) << 4; if (doTexture) + { id->d[0] |= (gstate_c.flipTexture & 1) << 5; + id->d[0] |= (doTextureProjection & 1) << 6; + } if (CanUseHardwareTransform(prim)) { id->d[0] |= 1 << 8; @@ -149,6 +153,7 @@ void GenerateVertexShader(int prim, char *buffer) { bool enableFog = gstate.isFogEnabled() && !gstate.isModeThrough() && !gstate.isModeClear(); bool throughmode = (gstate.vertType & GE_VTYPE_THROUGH_MASK) != 0; bool flipV = gstate_c.flipTexture; + bool doTextureProjection = gstate.getUVGenMode() == 1; DoLightComputation doLight[4] = {LIGHT_OFF, LIGHT_OFF, LIGHT_OFF, LIGHT_OFF}; if (hwXForm) { @@ -173,7 +178,12 @@ void GenerateVertexShader(int prim, char *buffer) { else WRITE(p, "attribute vec4 a_position;\n"); // need to pass the fog coord in w - if (doTexture) WRITE(p, "attribute vec2 a_texcoord;\n"); + if (doTexture) { + if (!hwXForm && doTextureProjection) + WRITE(p, "attribute vec3 a_texcoord;\n"); + else + WRITE(p, "attribute vec2 a_texcoord;\n"); + } if (hasColor) { WRITE(p, "attribute lowp vec4 a_color0;\n"); if (lmode && !hwXForm) // only software transform supplies color1 as vertex data @@ -240,7 +250,12 @@ void GenerateVertexShader(int prim, char *buffer) { WRITE(p, "varying lowp vec4 v_color0;\n"); if (lmode) WRITE(p, "varying lowp vec3 v_color1;\n"); - if (doTexture) WRITE(p, "varying vec2 v_texcoord;\n"); + if (doTexture) { + if (doTextureProjection) + WRITE(p, "varying vec3 v_texcoord;\n"); + else + WRITE(p, "varying vec2 v_texcoord;\n"); + } if (enableFog) WRITE(p, "varying float v_fogdepth;\n"); WRITE(p, "void main() {\n"); @@ -410,8 +425,8 @@ void GenerateVertexShader(int prim, char *buffer) { WRITE(p, " vec3 temp_tc = a_normal;\n"); break; } - // Transform by texture matrix - WRITE(p, " v_texcoord = (u_texmtx * vec4(temp_tc, 1.0)).xy;\n"); + // Transform by texture matrix. XYZ as we are doing projection mapping. + WRITE(p, " v_texcoord = (u_texmtx * vec4(temp_tc, 1.0)).xyz;\n"); break; case 2: // Shade mapping - use dots from light sources.