OpenGL Renderer:

- Move alpha testing to the fragment shader.
- Do a bunch of code cleanup.
This commit is contained in:
rogerman 2012-12-23 10:05:42 +00:00
parent cb1f8af8d7
commit 97ddd12360
2 changed files with 147 additions and 112 deletions

View File

@ -135,6 +135,8 @@ static GLint uniformTexScale;
static GLint uniformHasTexture; static GLint uniformHasTexture;
static GLint uniformTextureBlendingMode; static GLint uniformTextureBlendingMode;
static GLint uniformWBuffer; static GLint uniformWBuffer;
static GLint uniformEnableAlphaTest;
static GLint uniformAlphaTestRef;
static u16 currentToonTable16[32]; static u16 currentToonTable16[32];
static bool toonTableNeedsUpdate = true; static bool toonTableNeedsUpdate = true;
@ -470,9 +472,11 @@ static void OGLReset()
{ {
glUniform1f(uniformPolyAlpha, 1.0f); glUniform1f(uniformPolyAlpha, 1.0f);
glUniform2f(uniformTexScale, 1.0f, 1.0f); glUniform2f(uniformTexScale, 1.0f, 1.0f);
glUniform1i(uniformHasTexture, 0); glUniform1i(uniformHasTexture, GL_FALSE);
glUniform1i(uniformTextureBlendingMode, 0); glUniform1i(uniformTextureBlendingMode, 0);
glUniform1i(uniformWBuffer, 0); glUniform1i(uniformWBuffer, 0);
glUniform1i(uniformEnableAlphaTest, GL_TRUE);
glUniform1f(uniformAlphaTestRef, 0.0f);
ENDGL(); ENDGL();
} }
@ -545,8 +549,6 @@ static void expandFreeTextures()
static char OGLInit(void) static char OGLInit(void)
{ {
GLint loc = 0;
if(!oglrender_init) if(!oglrender_init)
return 0; return 0;
if(!oglrender_init()) if(!oglrender_init())
@ -555,28 +557,21 @@ static char OGLInit(void)
if(!BEGINGL()) if(!BEGINGL())
return 0; return 0;
for (u8 i = 0; i < 255; i++)
material_8bit_to_float[i] = (GLfloat)(i<<2)/255.f;
extString = (char*)glGetString(GL_EXTENSIONS);
expandFreeTextures();
glPixelStorei(GL_PACK_ALIGNMENT,8);
xglEnable (GL_NORMALIZE);
xglEnable (GL_DEPTH_TEST);
glEnable (GL_TEXTURE_1D);
glEnable (GL_TEXTURE_2D);
glAlphaFunc (GL_GREATER, 0);
xglEnable (GL_ALPHA_TEST);
glViewport(0, 0, 256, 192); glViewport(0, 0, 256, 192);
if (glGetError() != GL_NO_ERROR) if (glGetError() != GL_NO_ERROR)
return 0; return 0;
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); extString = (char*)glGetString(GL_EXTENSIONS);
for (u8 i = 0; i < 255; i++)
material_8bit_to_float[i] = (GLfloat)(i<<2)/255.f;
expandFreeTextures();
// Maintain our own vertex index buffer for vertex batching and primitive
// conversions. Such conversions are necessary since OpenGL deprecates
// primitives like GL_QUADS and GL_QUAD_STRIP in later versions.
vertIndexBuffer = new GLushort[VERT_INDEX_BUFFER_SIZE];
#ifndef __APPLE__ #ifndef __APPLE__
INITOGLEXT(PFNGLCREATESHADERPROC,glCreateShader) INITOGLEXT(PFNGLCREATESHADERPROC,glCreateShader)
@ -625,41 +620,7 @@ static char OGLInit(void)
INITOGLEXT(PFNGLACTIVETEXTUREPROC,glActiveTexture) INITOGLEXT(PFNGLACTIVETEXTUREPROC,glActiveTexture)
#endif #endif
/* Create the shaders */ // VBO Setup
createShaders();
/* Assign the texture units : 0 for main textures, 1 for toon table */
/* Also init the locations for some variables in the shaders */
if(isShaderSupported)
{
loc = glGetUniformLocation(shaderProgram, "tex2d");
glUniform1i(loc, 0);
loc = glGetUniformLocation(shaderProgram, "toonTable");
glUniform1i(loc, 1);
uniformPolyAlpha = glGetUniformLocation(shaderProgram, "polyAlpha");
uniformTexScale = glGetUniformLocation(shaderProgram, "texScale");
uniformHasTexture = glGetUniformLocation(shaderProgram, "hasTexture");
uniformTextureBlendingMode = glGetUniformLocation(shaderProgram, "texBlending");
uniformWBuffer = glGetUniformLocation(shaderProgram, "oglWBuffer");
}
//we want to use alpha destination blending so we can track the last-rendered alpha value
if(glBlendFuncSeparate != NULL)
{
if (glBlendEquationSeparate != NULL)
{
// test: new super mario brothers renders the stormclouds at the beginning
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_DST_ALPHA);
glBlendEquationSeparate( GL_FUNC_ADD, GL_MAX );
}
else
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_DST_ALPHA);
}
// VBO
isVBOSupported = (strstr(extString, "GL_ARB_vertex_buffer_object") == NULL)?false:true; isVBOSupported = (strstr(extString, "GL_ARB_vertex_buffer_object") == NULL)?false:true;
if (isVBOSupported) if (isVBOSupported)
{ {
@ -667,7 +628,7 @@ static char OGLInit(void)
glGenBuffersARB(1, &vboTexCoordID); glGenBuffersARB(1, &vboTexCoordID);
} }
// PBO // PBO Setup
isPBOSupported = (strstr(extString, "GL_ARB_pixel_buffer_object") == NULL)?false:true; isPBOSupported = (strstr(extString, "GL_ARB_pixel_buffer_object") == NULL)?false:true;
if (isPBOSupported) if (isPBOSupported)
{ {
@ -687,8 +648,35 @@ static char OGLInit(void)
gpuScreen3DHasNewData = false; gpuScreen3DHasNewData = false;
} }
// Render State Setup (common to both shaders and fixed-function pipeline)
xglEnable(GL_DEPTH_TEST);
glPixelStorei(GL_PACK_ALIGNMENT, 8);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//we want to use alpha destination blending so we can track the last-rendered alpha value
if(glBlendFuncSeparate != NULL)
{
if (glBlendEquationSeparate != NULL)
{
// test: new super mario brothers renders the stormclouds at the beginning
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_DST_ALPHA);
glBlendEquationSeparate( GL_FUNC_ADD, GL_MAX );
}
else
{
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_DST_ALPHA);
}
}
// Shader Setup
createShaders();
if(isShaderSupported) if(isShaderSupported)
{ {
// The toon table is a special 1D texture where each pixel corresponds
// to a specific color in the toon table.
//
// Set up the toon table and assign it to texture unit 1 (main textures
// will be on texture unit 0).
glGenTextures (1, &oglToonTableTextureID); glGenTextures (1, &oglToonTableTextureID);
glActiveTexture(GL_TEXTURE1); glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_1D, oglToonTableTextureID); glBindTexture(GL_TEXTURE_1D, oglToonTableTextureID);
@ -697,12 +685,32 @@ static char OGLInit(void)
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP); //clamp so that we dont run off the edges due to 1.0 -> [0,31] math glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP); //clamp so that we dont run off the edges due to 1.0 -> [0,31] math
glBindTexture(GL_TEXTURE_1D, 0); glBindTexture(GL_TEXTURE_1D, 0);
// Restore Toon table
memcpy(currentToonTable16, gfx3d.renderState.u16ToonTable, sizeof(currentToonTable16)); memcpy(currentToonTable16, gfx3d.renderState.u16ToonTable, sizeof(currentToonTable16));
toonTableNeedsUpdate = true; toonTableNeedsUpdate = true;
// Set up shader uniforms
GLint uniformTex2DSampler = glGetUniformLocation(shaderProgram, "tex2d");
glUniform1i(uniformTex2DSampler, 0);
GLint uniformToonTable = glGetUniformLocation(shaderProgram, "toonTable");
glUniform1i(uniformToonTable, 1);
uniformPolyAlpha = glGetUniformLocation(shaderProgram, "polyAlpha");
uniformTexScale = glGetUniformLocation(shaderProgram, "texScale");
uniformHasTexture = glGetUniformLocation(shaderProgram, "hasTexture");
uniformTextureBlendingMode = glGetUniformLocation(shaderProgram, "texBlending");
uniformWBuffer = glGetUniformLocation(shaderProgram, "oglWBuffer");
uniformEnableAlphaTest = glGetUniformLocation(shaderProgram, "enableAlphaTest");
uniformAlphaTestRef = glGetUniformLocation(shaderProgram, "alphaTestRef");
} }
else else
{ {
// Set up fixed-function pipeline render states.
xglEnable(GL_NORMALIZE);
glEnable(GL_TEXTURE_1D);
glEnable(GL_TEXTURE_2D);
glAlphaFunc(GL_GREATER, 0);
xglEnable(GL_ALPHA_TEST);
// Map the vertex list's colors with 4 floats per color. This is being done // Map the vertex list's colors with 4 floats per color. This is being done
// because OpenGL needs 4-colors per vertex to support translucency. (The DS // because OpenGL needs 4-colors per vertex to support translucency. (The DS
// uses 3-colors per vertex, and adds alpha through the poly, so we can't // uses 3-colors per vertex, and adds alpha through the poly, so we can't
@ -710,7 +718,7 @@ static char OGLInit(void)
color4fBuffer = new GLfloat[VERTLIST_SIZE * 4]; color4fBuffer = new GLfloat[VERTLIST_SIZE * 4];
} }
// FBO // FBO Setup
isFBOSupported = (strstr(extString, "GL_ARB_framebuffer_object") == NULL)?false:true; isFBOSupported = (strstr(extString, "GL_ARB_framebuffer_object") == NULL)?false:true;
if (isFBOSupported) if (isFBOSupported)
{ {
@ -763,14 +771,7 @@ static char OGLInit(void)
ENDGL(); ENDGL();
// Maintain our own vertex index buffer for vertex batching and primitive // Multithreading Setup
// conversions. Such conversions are necessary since OpenGL deprecates
// primitives like GL_QUADS and GL_QUAD_STRIP in later versions.
vertIndexBuffer = new GLushort[VERT_INDEX_BUFFER_SIZE];
OGLReset();
// Set up multithreading
isReadPixelsWorking = false; isReadPixelsWorking = false;
if (CommonSettings.num_cores > 1) if (CommonSettings.num_cores > 1)
@ -790,6 +791,9 @@ static char OGLInit(void)
enableMultithreading = false; enableMultithreading = false;
} }
// Initialization finished -- reset the renderer
OGLReset();
return 1; return 1;
} }
@ -904,13 +908,13 @@ static void setTexture(unsigned int format, unsigned int texpal)
{ {
if (format == 0 || currentTexParams.texFormat == TEXMODE_NONE) if (format == 0 || currentTexParams.texFormat == TEXMODE_NONE)
{ {
if(isShaderSupported && hasTexture) { glUniform1i(uniformHasTexture, 0); hasTexture = false; } if(isShaderSupported && hasTexture) { glUniform1i(uniformHasTexture, GL_FALSE); hasTexture = false; }
return; return;
} }
if(isShaderSupported) if(isShaderSupported)
{ {
if(!hasTexture) { glUniform1i(uniformHasTexture, 1); hasTexture = true; } if(!hasTexture) { glUniform1i(uniformHasTexture, GL_TRUE); hasTexture = true; }
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
} }
@ -1085,28 +1089,38 @@ static void SetupPolygonRender(POLY *thePoly)
static void Control() static void Control()
{ {
if (isShaderSupported)
{
if (gfx3d.renderState.enableTexturing) if (gfx3d.renderState.enableTexturing)
{ {
if (isShaderSupported) glUniform1i(uniformHasTexture, GL_TRUE);
{
glUniform1i(uniformHasTexture, 1);
} }
else else
{
glUniform1i(uniformHasTexture, GL_FALSE);
}
if(gfx3d.renderState.enableAlphaTest)
{
glUniform1i(uniformEnableAlphaTest, GL_TRUE);
}
else
{
glUniform1i(uniformEnableAlphaTest, GL_FALSE);
}
glUniform1f(uniformAlphaTestRef, divide5bitBy31LUT[gfx3d.renderState.alphaTestRef]);
}
else
{
if (gfx3d.renderState.enableTexturing)
{ {
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
} }
}
else
{
if (isShaderSupported)
{
glUniform1i(uniformHasTexture, 0);
}
else else
{ {
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
} }
}
if(gfx3d.renderState.enableAlphaTest && (gfx3d.renderState.alphaTestRef > 0)) if(gfx3d.renderState.enableAlphaTest && (gfx3d.renderState.alphaTestRef > 0))
{ {
@ -1116,6 +1130,7 @@ static void Control()
{ {
glAlphaFunc(GL_GREATER, 0); glAlphaFunc(GL_GREATER, 0);
} }
}
if(gfx3d.renderState.enableAlphaBlending) if(gfx3d.renderState.enableAlphaBlending)
{ {

View File

@ -47,56 +47,76 @@ const char *vertexShader = {"\
const char *fragmentShader = {"\ const char *fragmentShader = {"\
uniform sampler1D toonTable; \n\ uniform sampler1D toonTable; \n\
uniform sampler2D tex2d; \n\ uniform sampler2D tex2d; \n\
uniform int hasTexture; \n\ uniform bool hasTexture; \n\
uniform int texBlending; \n\ uniform int texBlending; \n\
uniform int oglWBuffer; \n\ uniform int oglWBuffer; \n\
uniform bool enableAlphaTest; \n\
uniform float alphaTestRef; \n\
\n\
varying vec4 pos; \n\ varying vec4 pos; \n\
varying vec4 vtxColor; \n\ varying vec4 vtxColor; \n\
\n\
void main() \n\ void main() \n\
{ \n\ { \n\
vec4 texColor = vec4(1.0, 1.0, 1.0, 1.0); \n\ vec4 texColor = vec4(1.0, 1.0, 1.0, 1.0); \n\
vec4 flagColor; \n\ vec4 flagColor; \n\
\ \n\
if(hasTexture != 0) \n\ if(hasTexture) \n\
{ \n\ { \n\
texColor = texture2D(tex2d, gl_TexCoord[0].st); \n\ texColor = texture2D(tex2d, gl_TexCoord[0].st); \n\
} \n\ } \n\
\n\
flagColor = texColor; \n\ flagColor = texColor; \n\
\n\
if(texBlending == 0) \n\ if(texBlending == 0) \n\
{ \n\ { \n\
flagColor = vtxColor * texColor; \n\ flagColor = vtxColor * texColor; \n\
} \n\ } \n\
else \n\ else if(texBlending == 1) \n\
if(texBlending == 1) \n\
{ \n\ { \n\
if (texColor.a == 0.0 || hasTexture == 0) \n\ if (texColor.a == 0.0 || !hasTexture) \n\
flagColor.rgb = vtxColor.rgb;\n\ { \n\
else \n\ flagColor.rgb = vtxColor.rgb; \n\
if (texColor.a == 1.0) \n\ } \n\
flagColor.rgb = texColor.rgb;\n\ else if (texColor.a == 1.0) \n\
else \n\ { \n\
flagColor.rgb = texColor.rgb * (1.0-texColor.a) + vtxColor.rgb * texColor.a;\n\ flagColor.rgb = texColor.rgb; \n\
flagColor.a = vtxColor.a; \n\
} \n\ } \n\
else \n\ else \n\
if(texBlending == 2) \n\ { \n\
flagColor.rgb = texColor.rgb * (1.0-texColor.a) + vtxColor.rgb * texColor.a;\n\
} \n\
\n\
flagColor.a = vtxColor.a; \n\
} \n\
else if(texBlending == 2) \n\
{ \n\ { \n\
vec3 toonColor = vec3(texture1D(toonTable, vtxColor.r).rgb); \n\ vec3 toonColor = vec3(texture1D(toonTable, vtxColor.r).rgb); \n\
flagColor.rgb = texColor.rgb * toonColor.rgb;\n\ flagColor.rgb = texColor.rgb * toonColor.rgb;\n\
flagColor.a = texColor.a * vtxColor.a;\n\ flagColor.a = texColor.a * vtxColor.a;\n\
} \n\ } \n\
else \n\ else if(texBlending == 3) \n\
if(texBlending == 3) \n\
{ \n\ { \n\
vec3 toonColor = vec3(texture1D(toonTable, vtxColor.r).rgb); \n\ vec3 toonColor = vec3(texture1D(toonTable, vtxColor.r).rgb); \n\
flagColor.rgb = texColor.rgb * vtxColor.rgb + toonColor.rgb; \n\ flagColor.rgb = texColor.rgb * vtxColor.rgb + toonColor.rgb; \n\
flagColor.a = texColor.a * vtxColor.a; \n\ flagColor.a = texColor.a * vtxColor.a; \n\
} \n\ } \n\
\n\
if (flagColor.a == 0.0 || (enableAlphaTest && flagColor.a < alphaTestRef)) \n\
{ \n\
discard; \n\
} \n\
\n\
if (oglWBuffer == 1) \n\ if (oglWBuffer == 1) \n\
{ \n\
// TODO \n\ // TODO \n\
gl_FragDepth = (pos.z / pos.w) * 0.5 + 0.5; \n\ gl_FragDepth = (pos.z / pos.w) * 0.5 + 0.5; \n\
} \n\
else \n\ else \n\
{ \n\
gl_FragDepth = (pos.z / pos.w) * 0.5 + 0.5; \n\ gl_FragDepth = (pos.z / pos.w) * 0.5 + 0.5; \n\
} \n\
\n\
gl_FragColor = flagColor; \n\ gl_FragColor = flagColor; \n\
} \n\ } \n\
"}; "};