preliminary microtexture

This commit is contained in:
Ian Curtis 2016-05-04 00:35:07 +00:00
parent 396fba7d24
commit c545b9fd85
6 changed files with 82 additions and 39 deletions

View file

@ -37,6 +37,7 @@ struct Mesh
{ {
// texture // texture
int format, x, y, width, height = 0; int format, x, y, width, height = 0;
bool microTexture = false;
bool mirrorU = false; bool mirrorU = false;
bool mirrorV = false; bool mirrorV = false;
@ -47,7 +48,6 @@ struct Mesh
bool textureAlpha = false; // use alpha in texture bool textureAlpha = false; // use alpha in texture
bool alphaTest = false; // discard fragment based on alpha (ogl does this with fixed function) bool alphaTest = false; // discard fragment based on alpha (ogl does this with fixed function)
bool lighting = false; bool lighting = false;
bool testBit = false;
bool clockWise = true; // we need to check if the matrix will change the winding bool clockWise = true; // we need to check if the matrix will change the winding
float fogIntensity = 1.0f; float fogIntensity = 1.0f;

View file

@ -126,10 +126,20 @@ void CNew3D::RenderScene(int priority, bool alpha)
} }
if (mesh.textured) { if (mesh.textured) {
auto tex = m_texSheet.BindTexture(m_textureRAM, mesh.format, mesh.mirrorU, mesh.mirrorV, mesh.x + m.textureOffsetX, mesh.y + m.textureOffsetY, mesh.width, mesh.height); auto tex1 = m_texSheet.BindTexture(m_textureRAM, mesh.format, mesh.mirrorU, mesh.mirrorV, mesh.x + m.textureOffsetX, mesh.y + m.textureOffsetY, mesh.width, mesh.height);
if (tex) { if (tex1) {
tex->BindTexture(); tex1->BindTexture();
tex->SetWrapMode(mesh.mirrorU, mesh.mirrorV); tex1->SetWrapMode(mesh.mirrorU, mesh.mirrorV);
}
if (mesh.microTexture) {
glActiveTexture(GL_TEXTURE1);
auto tex2 = m_texSheet.BindTexture(m_textureRAM, 0, true, true, 0, 1024, 128, 128);
if (tex2) {
tex2->BindTexture();
tex2->SetWrapMode(mesh.mirrorU, mesh.mirrorV);
}
glActiveTexture(GL_TEXTURE0);
} }
} }
@ -853,13 +863,14 @@ void CNew3D::CacheModel(Model *m, const UINT32 *data)
} }
if (ph.TexEnabled()) { if (ph.TexEnabled()) {
currentMesh->format = ph.TexFormat(); currentMesh->format = ph.TexFormat();
currentMesh->x = ph.X(); currentMesh->x = ph.X();
currentMesh->y = ph.Y(); currentMesh->y = ph.Y();
currentMesh->width = ph.TexWidth(); currentMesh->width = ph.TexWidth();
currentMesh->height = ph.TexHeight(); currentMesh->height = ph.TexHeight();
currentMesh->mirrorU = ph.TexUMirror(); currentMesh->mirrorU = ph.TexUMirror();
currentMesh->mirrorV = ph.TexVMirror(); currentMesh->mirrorV = ph.TexVMirror();
currentMesh->microTexture = ph.MicroTexture();
} }
} }

View file

@ -163,6 +163,11 @@ bool PolyHeader::TexVMirror()
return (header[2] & 1) > 0; return (header[2] & 1) > 0;
} }
bool PolyHeader::MicroTexture()
{
return (header[2] & 0x10) > 0;
}
// //
// header 3 // header 3

View file

@ -29,9 +29,10 @@ xxxxxxxx xxxxxxxx xxxxxxxx-------- Polygon normal X coordinate(2.22 fixed point
0x02: 0x02:
xxxxxxxx xxxxxxxx xxxxxxxx -------- Polygon normal Y coordinate(2.22 fixed point) xxxxxxxx xxxxxxxx xxxxxxxx -------- Polygon normal Y coordinate(2.22 fixed point)
-------- -------- -------- ---x---- Microtexture (aka multitexture)
-------- -------- -------- ------x- Texture U mirror enable -------- -------- -------- ------x- Texture U mirror enable
-------- -------- -------- -------x Texture V mirror enable -------- -------- -------- -------x Texture V mirror enable
-------- -------- -------- xxxxxx-- H/W also supports texture clamp/mirror, so guessing some of these bits must be that -------- -------- -------- xxx-xx-- I think first 3 bits might be microtex number 0-7, next 2 maybe UV un-smooth wrap
0x03: 0x03:
xxxxxxxx xxxxxxxx xxxxxxxx -------- Polygon normal Z coordinate(2.22 fixed point) xxxxxxxx xxxxxxxx xxxxxxxx -------- Polygon normal Z coordinate(2.22 fixed point)
@ -100,6 +101,7 @@ public:
//header 2 //header 2
bool TexUMirror(); bool TexUMirror();
bool TexVMirror(); bool TexVMirror();
bool MicroTexture();
// header 3 // header 3
int TexWidth(); int TexWidth();

View file

@ -33,14 +33,17 @@ static const char *vertexShaderBasic =
static const char *fragmentShaderBasic = static const char *fragmentShaderBasic =
"uniform sampler2D tex;\n" "uniform sampler2D tex1;\n" // base tex
"uniform sampler2D tex2;\n" // micro tex (optional)
"uniform int textureEnabled;\n" "uniform int textureEnabled;\n"
"uniform int microTexture;\n"
"uniform int alphaTest;\n" "uniform int alphaTest;\n"
"uniform int textureAlpha;\n" "uniform int textureAlpha;\n"
"uniform vec3 fogColour;\n" "uniform vec3 fogColour;\n"
"uniform vec4 spotEllipse;\n" // spotlight ellipse position: .x=X position (screen coordinates), .y=Y position, .z=half-width, .w=half-height) "uniform vec4 spotEllipse;\n" // spotlight ellipse position: .x=X position (screen coordinates), .y=Y position, .z=half-width, .w=half-height)
"uniform vec2 spotRange;\n" // spotlight Z range: .x=start (viewspace coordinates), .y=limit "uniform vec2 spotRange;\n" // spotlight Z range: .x=start (viewspace coordinates), .y=limit
"uniform vec3 spotColor;\n" // spotlight RGB color "uniform vec3 spotColor;\n" // spotlight RGB color
"uniform vec3 lighting[2];\n" // lighting state (lighting[0] = sun direction, lighting[1].x,y = diffuse, ambient intensities from 0-1.0) "uniform vec3 lighting[2];\n" // lighting state (lighting[0] = sun direction, lighting[1].x,y = diffuse, ambient intensities from 0-1.0)
"uniform int lightEnable;\n" // lighting enabled (1.0) or luminous (0.0), drawn at full intensity "uniform int lightEnable;\n" // lighting enabled (1.0) or luminous (0.0), drawn at full intensity
"uniform float shininess;\n" // specular shininess (if >= 0.0) or disable specular lighting (negative) "uniform float shininess;\n" // specular shininess (if >= 0.0) or disable specular lighting (negative)
@ -53,27 +56,37 @@ static const char *fragmentShaderBasic =
"void main()\n" "void main()\n"
"{\n" "{\n"
"vec4 texData;\n" "vec4 tex1Data;\n"
"vec4 colData;\n" "vec4 colData;\n"
"vec4 finalData;\n" "vec4 finalData;\n"
"texData = vec4(1.0, 1.0, 1.0, 1.0);\n" "tex1Data = vec4(1.0, 1.0, 1.0, 1.0);\n"
// Done this way because some older GPUs have difficulty with nested if- "if(textureEnabled==1) {\n"
// statements (e.g., NVS 300)
"if (textureEnabled == 1) {\n" "tex1Data = texture2D( tex1, gl_TexCoord[0].st);\n"
"texData = texture2D( tex, gl_TexCoord[0].st);\n"
"}\n" "if (microTexture==1) {\n"
"if (textureEnabled == 1 && alphaTest == 1 && texData.a < (8.0/16.0)) {\n" "vec4 tex2Data = texture2D( tex2, gl_TexCoord[0].st*4);\n"
"discard;\n"
"}\n" "tex1Data = (tex1Data+tex2Data)/2.0;\n"
"if (textureEnabled == 1 && textureAlpha == 0) {\n" "}\n"
"texData.a = 1.0;\n"
"if (alphaTest==1) {\n" // does it make any sense to do this later?
"if (tex1Data.a < (8.0/16.0)) {\n"
"discard;\n"
"}\n"
"}\n"
"if (textureAlpha == 0) {\n"
"tex1Data.a = 1.0;\n"
"}\n"
"}\n" "}\n"
"colData = gl_Color;\n" "colData = gl_Color;\n"
"finalData = texData * colData;\n" "finalData = tex1Data * colData;\n"
"if (finalData.a < (1.0/16.0)) {\n" // basically chuck out any totally transparent pixels value = 1/16 the smallest transparency level h/w supports "if (finalData.a < (1.0/16.0)) {\n" // basically chuck out any totally transparent pixels value = 1/16 the smallest transparency level h/w supports
"discard;\n" "discard;\n"
"}\n" "}\n"
@ -137,7 +150,8 @@ R3DShader::R3DShader()
void R3DShader::Start() void R3DShader::Start()
{ {
m_textured = false; m_textured1 = false;
m_textured2 = false;
m_textureAlpha = false; // use alpha in texture m_textureAlpha = false; // use alpha in texture
m_alphaTest = false; // discard fragment based on alpha (ogl does this with fixed function) m_alphaTest = false; // discard fragment based on alpha (ogl does this with fixed function)
m_doubleSided = false; m_doubleSided = false;
@ -171,8 +185,10 @@ bool R3DShader::LoadShader(const char* vertexShader, const char* fragmentShader)
success = LoadShaderProgram(&m_shaderProgram, &m_vertexShader, &m_fragmentShader, nullptr, nullptr, vShader, fShader); success = LoadShaderProgram(&m_shaderProgram, &m_vertexShader, &m_fragmentShader, nullptr, nullptr, vShader, fShader);
m_locTexture = glGetUniformLocation(m_shaderProgram, "tex"); m_locTexture1 = glGetUniformLocation(m_shaderProgram, "tex1");
m_locTextureEnabled = glGetUniformLocation(m_shaderProgram, "textureEnabled"); m_locTexture2 = glGetUniformLocation(m_shaderProgram, "tex2");
m_locTexture1Enabled= glGetUniformLocation(m_shaderProgram, "textureEnabled");
m_locTexture2Enabled= glGetUniformLocation(m_shaderProgram, "microTexture");
m_locTextureAlpha = glGetUniformLocation(m_shaderProgram, "textureAlpha"); m_locTextureAlpha = glGetUniformLocation(m_shaderProgram, "textureAlpha");
m_locAlphaTest = glGetUniformLocation(m_shaderProgram, "alphaTest"); m_locAlphaTest = glGetUniformLocation(m_shaderProgram, "alphaTest");
@ -209,12 +225,18 @@ void R3DShader::SetMeshUniforms(const Mesh* m)
} }
if (m_dirtyMesh) { if (m_dirtyMesh) {
glUniform1i(m_locTexture, 0); glUniform1i(m_locTexture1, 0);
glUniform1i(m_locTexture2, 1);
} }
if (m_dirtyMesh || m->textured != m_textured) { if (m_dirtyMesh || m->textured != m_textured1) {
glUniform1i(m_locTextureEnabled, m->textured); glUniform1i(m_locTexture1Enabled, m->textured);
m_textured = m->textured; m_textured1 = m->textured;
}
if (m_dirtyMesh || m->microTexture != m_textured2) {
glUniform1i(m_locTexture2Enabled, m->microTexture);
m_textured2 = m->microTexture;
} }
if (m_dirtyMesh || m->alphaTest != m_alphaTest) { if (m_dirtyMesh || m->alphaTest != m_alphaTest) {

View file

@ -26,13 +26,16 @@ private:
GLuint m_fragmentShader; GLuint m_fragmentShader;
// mesh uniform locations // mesh uniform locations
GLint m_locTexture; GLint m_locTexture1;
GLint m_locTextureEnabled; GLint m_locTexture2;
GLint m_locTexture1Enabled;
GLint m_locTexture2Enabled;
GLint m_locTextureAlpha; GLint m_locTextureAlpha;
GLint m_locAlphaTest; GLint m_locAlphaTest;
// cached mesh values // cached mesh values
bool m_textured; bool m_textured1;
bool m_textured2;
bool m_textureAlpha; // use alpha in texture bool m_textureAlpha; // use alpha in texture
bool m_alphaTest; // discard fragment based on alpha (ogl does this with fixed function) bool m_alphaTest; // discard fragment based on alpha (ogl does this with fixed function)
float m_fogIntensity; float m_fogIntensity;