Added shaders for better 3D graphics

Fixed toon table uploading
GL extensions should now work under Linux with glXGetProcAddress (not tested)
GFX3D::HIGHLIGHT is now 1 as it's supposed to be
This commit is contained in:
luigi__ 2008-12-04 19:48:46 +00:00
parent bae065318f
commit 5c457346db
3 changed files with 256 additions and 62 deletions

View File

@ -72,6 +72,8 @@ static void ENDGL() {
#include "OGLRender.h"
#include "gfx3d.h"
#include "shaders.h"
#ifndef CTASSERT
#define CTASSERT(x) typedef char __assert ## y[(x) ? 1 : -1]
#endif
@ -97,6 +99,7 @@ static bool wireframe=false, alpha31=false;
static unsigned int polyID=0;
static unsigned int depthFuncMode=0;
static unsigned int envMode=0;
static unsigned int lastEnvMode=0;
static unsigned int cullingMask=0;
static bool alphaDepthWrite;
static unsigned int lightMask=0;
@ -104,10 +107,13 @@ static bool isTranslucent;
//------------------------------------------------------------
#ifdef _WIN32
#define OGLEXT(x,y) x y = 0;
#ifdef _WIN32
#define INITOGLEXT(x,y) y = (x)wglGetProcAddress(#y);
#else
#define INITOGLEXT(x,y) y = (x)glXGetProcAddress(#y);
#endif
OGLEXT(PFNGLCREATESHADERPROC,glCreateShader)
//zero: i dont understand this at all. my glext.h has the wrong thing declared here... so I have to do it myself
@ -118,14 +124,16 @@ OGLEXT(PFNGLCREATEPROGRAMPROC,glCreateProgram)
OGLEXT(PFNGLATTACHSHADERPROC,glAttachShader)
OGLEXT(PFNGLLINKPROGRAMPROC,glLinkProgram)
OGLEXT(PFNGLUSEPROGRAMPROC,glUseProgram)
OGLEXT(PFNGLGETSHADERIVPROC,glGetShaderiv)
OGLEXT(PFNGLGETSHADERINFOLOGPROC,glGetShaderInfoLog)
OGLEXT(PFNGLDELETESHADERPROC,glDeleteShader)
OGLEXT(PFNGLGETPROGRAMIVPROC,glGetProgramiv)
OGLEXT(PFNGLGETPROGRAMINFOLOGPROC,glGetProgramInfoLog)
OGLEXT(PFNGLVALIDATEPROGRAMPROC,glValidateProgram)
OGLEXT(PFNGLBLENDFUNCSEPARATEEXTPROC,glBlendFuncSeparateEXT)
#else
#define INITOGLEXT(x,y) y = 0;
#endif
OGLEXT(PFNGLGETUNIFORMLOCATIONPROC,glGetUniformLocation)
OGLEXT(PFNGLUNIFORM1IPROC,glUniform1i)
OGLEXT(PFNGLACTIVETEXTUREPROC,glActiveTexture)
//opengl state caching:
@ -148,6 +156,7 @@ static void xglPolygonMode(GLenum face,GLenum mode) {
}
}
#if 0
#ifdef _WIN32
static void xglUseProgram(GLuint program) {
if(!glUseProgram) return;
@ -163,6 +172,7 @@ static void xglUseProgram(GLuint program) {
}
#endif
#endif
#endif
static void xglDepthMask (GLboolean flag) {
static GLboolean oldflag = -1;
@ -237,7 +247,104 @@ u32 texcache_stop;
GLenum oglTempTextureID[MAX_TEXTURE];
GLenum oglToonTableTextureID;
u32 toonShader, toonProgram;
#define NOSHADERS(i) { hasShaders = false; INFO("Shaders aren't supported on your system, using fixed pipeline\n(failed shader init at step %i)\n", i); return; }
#define SHADER_COMPCHECK(s) { \
GLint status = GL_TRUE; \
glGetShaderiv(s, GL_COMPILE_STATUS, &status); \
if(status != GL_TRUE) \
{ \
GLint logSize; \
GLchar *log; \
glGetShaderiv(s, GL_INFO_LOG_LENGTH, &logSize); \
log = new GLchar[logSize]; \
glGetShaderInfoLog(s, logSize, &logSize, log); \
INFO("SEVERE : FAILED TO COMPILE GL SHADER : %s\n", log); \
delete log; \
if(s)glDeleteShader(s); \
NOSHADERS(3); \
} \
}
#define PROGRAM_COMPCHECK(p, s1, s2) { \
GLint status = GL_TRUE; \
glGetProgramiv(p, GL_LINK_STATUS, &status); \
if(status != GL_TRUE) \
{ \
GLint logSize; \
GLchar *log; \
glGetProgramiv(p, GL_INFO_LOG_LENGTH, &logSize); \
log = new GLchar[logSize]; \
glGetProgramInfoLog(p, logSize, &logSize, log); \
INFO("SEVERE : FAILED TO LINK GL SHADER PROGRAM : %s\n", log); \
delete log; \
if(s1)glDeleteShader(s1); \
if(s2)glDeleteShader(s2); \
NOSHADERS(5); \
} \
}
bool hasShaders = false;
/* Vertex shader */
GLuint vertexShaderID;
/* Fragment shader */
GLuint fragmentShaderID;
/* Shader program */
GLuint shaderProgram;
static GLuint hasTexLoc;
static GLuint texBlendLoc;
/* Shaders init */
void createShaders()
{
hasShaders = true;
if (!glCreateShader ||
!glShaderSource ||
!glCompileShader ||
!glCreateProgram ||
!glAttachShader ||
!glLinkProgram ||
!glUseProgram ||
!glGetShaderInfoLog)
NOSHADERS(1);
vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
if(!vertexShaderID)
NOSHADERS(2);
glShaderSource(vertexShaderID, 1, (GLchar**)&vertexShader, NULL);
glCompileShader(vertexShaderID);
SHADER_COMPCHECK(vertexShaderID);
fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
if(!fragmentShaderID)
NOSHADERS(2);
glShaderSource(fragmentShaderID, 1, (GLchar**)&fragmentShader, NULL);
glCompileShader(fragmentShaderID);
SHADER_COMPCHECK(fragmentShaderID);
shaderProgram = glCreateProgram();
if(!shaderProgram)
NOSHADERS(4);
glAttachShader(shaderProgram, vertexShaderID);
glAttachShader(shaderProgram, fragmentShaderID);
glLinkProgram(shaderProgram);
PROGRAM_COMPCHECK(shaderProgram, vertexShaderID, fragmentShaderID);
glValidateProgram(shaderProgram);
glUseProgram(shaderProgram);
INFO("Successfully created OpenGL shaders.\n");
}
//=================================================
@ -260,6 +367,8 @@ static void Reset()
static char Init(void)
{
GLuint loc;
if(!oglrender_init)
return 0;
if(!oglrender_init())
@ -272,6 +381,7 @@ static char Init(void)
xglEnable (GL_NORMALIZE);
xglEnable (GL_DEPTH_TEST);
glEnable (GL_TEXTURE_1D);
glEnable (GL_TEXTURE_2D);
glAlphaFunc (GL_GREATER, 0);
@ -285,7 +395,6 @@ static char Init(void)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
#ifdef _WIN32
INITOGLEXT(PFNGLCREATESHADERPROC,glCreateShader)
INITOGLEXT(X_PFNGLGETSHADERSOURCEPROC,glShaderSource)
INITOGLEXT(PFNGLCOMPILESHADERPROC,glCompileShader)
@ -293,8 +402,33 @@ static char Init(void)
INITOGLEXT(PFNGLATTACHSHADERPROC,glAttachShader)
INITOGLEXT(PFNGLLINKPROGRAMPROC,glLinkProgram)
INITOGLEXT(PFNGLUSEPROGRAMPROC,glUseProgram)
INITOGLEXT(PFNGLGETSHADERIVPROC,glGetShaderiv)
INITOGLEXT(PFNGLGETSHADERINFOLOGPROC,glGetShaderInfoLog)
INITOGLEXT(PFNGLDELETESHADERPROC,glDeleteShader)
INITOGLEXT(PFNGLGETPROGRAMIVPROC,glGetProgramiv)
INITOGLEXT(PFNGLGETPROGRAMINFOLOGPROC,glGetProgramInfoLog)
INITOGLEXT(PFNGLVALIDATEPROGRAMPROC,glValidateProgram)
INITOGLEXT(PFNGLBLENDFUNCSEPARATEEXTPROC,glBlendFuncSeparateEXT)
INITOGLEXT(PFNGLGETUNIFORMLOCATIONPROC,glGetUniformLocation)
INITOGLEXT(PFNGLUNIFORM1IPROC,glUniform1i)
INITOGLEXT(PFNGLACTIVETEXTUREPROC,glActiveTexture)
/* Create the shaders */
createShaders();
/* Assign the texture units : 0 for main textures, 1 for toon table */
/* Also init the locations for some variables in the shaders */
if(hasShaders)
{
loc = glGetUniformLocation(shaderProgram, "tex2d");
glUniform1i(loc, 0);
loc = glGetUniformLocation(shaderProgram, "toonTable");
glUniform1i(loc, 1);
hasTexLoc = glGetUniformLocation(shaderProgram, "hasTexture");
texBlendLoc = glGetUniformLocation(shaderProgram, "texBlending");
}
//we want to use alpha destination blending so we can track the last-rendered alpha value
if(glBlendFuncSeparateEXT)
@ -302,51 +436,17 @@ static char Init(void)
glBlendFuncSeparateEXT(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_DST_ALPHA);
}
if(glCreateShader && glShaderSource && glCompileShader && glCreateProgram && glAttachShader && glLinkProgram && glUseProgram && glGetShaderInfoLog)
{
{
glGenTextures (1, &oglToonTableTextureID);
glBindTexture(GL_TEXTURE_1D,oglToonTableTextureID);
glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
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
//do we need to init the toon table?
}
{
char buf[10000];
const char* toonShaderSource[] = {"\
uniform sampler2D tex2; \
uniform sampler1D tex1; \
void main() {\
gl_FragColor = gl_Color; \
gl_FragColor = texture1D(tex1,gl_FragColor.r/32*31); \
gl_FragColor *= texture2D(tex2,gl_TexCoord[0].st); \
}\
"};
glGenTextures (1, &oglToonTableTextureID);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_1D, oglToonTableTextureID);
glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
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
//TODO - this should modulate or add depending on whether we are in highlight or toon mode
toonShader = glCreateShader(GL_FRAGMENT_SHADER);
toonProgram = glCreateProgram();
glShaderSource(toonShader, 1, (GLchar**)toonShaderSource, 0);
glCompileShader(toonShader);
glGetShaderInfoLog(toonShader,10000,0,buf);
glAttachShader(toonProgram,toonShader);
glLinkProgram(toonProgram);
toonShader = 0;
}
}
#endif
#ifdef _WIN32
if(!glBlendFuncSeparateEXT)
#endif
clearAlpha = 1;
#ifdef _WIN32
else clearAlpha = 0;
#endif
else
clearAlpha = 0;
ENDGL();
@ -463,6 +563,7 @@ static void DebugDumpTexture(int which)
//================================================================================
static int lastTexture = -1;
static bool hasTexture = false;
static void setTexture(unsigned int format, unsigned int texpal)
{
int palSize[7]={32,4,16,256,0,8,32768};
@ -486,14 +587,22 @@ static void setTexture(unsigned int format, unsigned int texpal)
if (format==0)
{
texcache_count=-1;
if(hasShaders && hasTexture) { glUniform1i(hasTexLoc, 0); hasTexture = false; }
return;
}
if (textureMode==0)
{
texcache_count=-1;
if(hasShaders && hasTexture) { glUniform1i(hasTexLoc, 0); hasTexture = false; }
return;
}
if(hasShaders)
{
if(!hasTexture) { glUniform1i(hasTexLoc, 1); hasTexture = true; }
glActiveTexture(GL_TEXTURE0);
}
txt_slot_current=(format>>14)&0x03;
adr=(unsigned char *)(ARM9Mem.textureSlotAddr[txt_slot_current]+((format&0x3FFF)<<3));
@ -801,7 +910,7 @@ static void setTexture(unsigned int format, unsigned int texpal)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (BIT16(texcache[i].frm) ? (BIT18(texcache[i].frm)?GL_MIRRORED_REPEAT:GL_REPEAT) : GL_CLAMP));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (BIT17(texcache[i].frm) ? (BIT18(texcache[i].frm)?GL_MIRRORED_REPEAT:GL_REPEAT) : GL_CLAMP));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (BIT17(texcache[i].frm) ? (BIT19(texcache[i].frm)?GL_MIRRORED_REPEAT:GL_REPEAT) : GL_CLAMP));
}
@ -880,14 +989,16 @@ static void BeginRenderPoly()
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, texEnv[envMode]);
//handle toon rendering
#ifdef _WIN32
if(glUseProgram) {
if(envMode == 2) {
xglUseProgram(toonProgram);
} else xglUseProgram(0);
if(hasShaders)
{
if(envMode != lastEnvMode)
{
lastEnvMode = envMode;
int _envModes[4] = {0, 1, (2 + gfx3d.shading), 0};
glUniform1i(texBlendLoc, _envModes[envMode]);
}
}
#endif
xglDepthMask(enableDepthWrite?GL_TRUE:GL_FALSE);
}
@ -945,7 +1056,12 @@ static void Render()
Control();
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx3d.rgbToonTable);
if(hasShaders)
{
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_1D, oglToonTableTextureID);
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx3d.rgbToonTable);
}
xglDepthMask(GL_TRUE);

View File

@ -91,7 +91,7 @@ struct GFX3D
BOOL enableTexturing, enableAlphaTest, enableAlphaBlending, enableAntialiasing, enableEdgeMarking;
static const u32 TOON = 0;
static const u32 HIGHLIGHT = 0;
static const u32 HIGHLIGHT = 1;
u32 shading;
POLYLIST* polylist;

78
desmume/src/shaders.h Normal file
View File

@ -0,0 +1,78 @@
/* Predefined OpenGL shaders */
/* Vertex shader */
const char *vertexShader = {"\
void main() \n\
{ \n\
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; \n\
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; \n\
gl_FrontColor = gl_Color; \n\
} \n\
"};
/* Fragment shader */
const char *fragmentShader = {"\
uniform sampler1D toonTable; \n\
uniform sampler2D tex2d; \n\
uniform int hasTexture; \n\
uniform int texBlending; \n\
\n\
vec4 float_to_6bit(in vec4 color) \n\
{ \n\
vec4 ret = color * 31;\n\
\n\
if(ret.r > 0) ret.r = (ret.r * 2) + 1; \n\
if(ret.g > 0) ret.g = (ret.g * 2) + 1; \n\
if(ret.b > 0) ret.b = (ret.b * 2) + 1; \n\
if(ret.a > 0) ret.a = (ret.a * 2) + 1; \n\
\n\
return ret; \n\
} \n\
\n\
void main() \n\
{ \n\
vec4 vtxColor = float_to_6bit(gl_Color); \n\
vec4 texColor = float_to_6bit(texture2D(tex2d, gl_TexCoord[0].st)); \n\
vec3 toonColor = vec3(float_to_6bit(vec4(texture1D(toonTable, gl_Color.r).rgb, 0.0))); \n\
vec4 fragColor = vec4(0.0, 0.0, 0.0, 0.0); \n\
\n\
if(hasTexture == 0) \n\
{ \n\
texColor = vec4(63.0, 63.0, 63.0, 63.0); \n\
} \n\
\n\
if(texBlending == 0) \n\
{ \n\
fragColor = ((texColor + 1) * (vtxColor + 1) - 1) / 64; \n\
} \n\
else if(texBlending == 1) \n\
{ \n\
if(texColor.a == 0.0 || hasTexture == 0) \n\
{ \n\
fragColor.rgb = vtxColor.rgb; \n\
} \n\
else if(texColor.a == 63.0) \n\
{ \n\
fragColor.rgb = texColor.rgb; \n\
} \n\
else \n\
{ \n\
fragColor.rgb = ((texColor.rgb * texColor.a) + (vtxColor.rgb * (63.0 - texColor.a))) / 64; \n\
} \n\
\n\
fragColor.a = vtxColor.a; \n\
} \n\
else if(texBlending == 2) \n\
{ \n\
fragColor.rgb = ((texColor.rgb + 1) * (toonColor + 1) - 1) / 64; \n\
fragColor.a = ((texColor.a + 1) * (vtxColor.a + 1) - 1) / 64; \n\
} \n\
else if(texBlending == 3) \n\
{ \n\
fragColor.rgb = min((((texColor.rgb + 1) * (toonColor + 1) - 1) / 64) + toonColor, 63.0); \n\
fragColor.a = ((texColor.a + 1) * (vtxColor.a + 1) - 1) / 64; \n\
} \n\
\n\
gl_FragColor = ((fragColor - 1) / 2) / 31; \n\
} \n\
"};