Permalink
Browse files

Add possibility to give each model its own shader through a new optio…

…nal SHADERS directive in the PIE file.
  • Loading branch information...
1 parent daff1e6 commit 465894d7b9d36f103a2bf196077bd9071ab75757 @perim perim committed Sep 2, 2013
View
@@ -39,6 +39,7 @@ iIMDShape::iIMDShape()
normalpage = iV_TEX_INVALID;
specularpage = iV_TEX_INVALID;
numFrames = 0;
+ shaderProgram = 0;
}
//*************************************************************************
@@ -81,6 +82,7 @@ void iV_IMDRelease(iIMDShape *s)
s->shadowEdgeList = NULL;
}
glDeleteBuffers(VBO_COUNT, s->buffers);
+ // shader deleted later, if any
d = s->next;
delete s;
iV_IMDRelease(d);
@@ -29,6 +29,7 @@
#include "lib/framework/frameresource.h"
#include "lib/framework/fixedpoint.h"
#include "lib/ivis_opengl/piematrix.h"
+#include "lib/ivis_opengl/piestate.h"
#include "ivisdef.h" // for imd structures
#include "imd.h" // for imd structures
@@ -670,6 +671,7 @@ iIMDShape *iV_ProcessIMD( const char **ppFileData, const char *FileDataEnd )
int32_t imd_version;
uint32_t imd_flags;
bool bTextured = false;
+ GLuint shader = 0;
memset(normalfile, 0, sizeof(normalfile));
memset(specfile, 0, sizeof(specfile));
@@ -804,8 +806,7 @@ iIMDShape *iV_ProcessIMD( const char **ppFileData, const char *FileDataEnd )
char ch, texType[PATH_MAX];
int i;
- /* the first parameter for textures is always ignored; which is why we ignore
- * nlevels read in above */
+ /* the first parameter for textures is always ignored; which is why we ignore nlevels read in above */
ch = *pFileData++;
// Run up to the dot or till the buffer is filled. Leave room for the extension.
@@ -838,6 +839,30 @@ iIMDShape *iV_ProcessIMD( const char **ppFileData, const char *FileDataEnd )
pFileData += cnt;
}
+ if (strncmp(buffer, "SHADERS", 7) == 0)
+ {
+ char vertex[PATH_MAX], fragment[PATH_MAX];
+
+ /* the first parameter for "textures" is always ignored; which is why we ignore nlevels read in above */
+ pFileData++;
+
+ if (sscanf(pFileData, "%255s %255s%n", vertex, fragment, &cnt) != 2)
+ {
+ debug(LOG_ERROR, "%s shader corrupt: %s", pFileName, buffer);
+ return NULL;
+ }
+ pFileData += cnt;
+ shader = pie_LoadShader("", vertex, fragment);
+
+ /* Try -yet again- to read in LEVELS directive */
+ if (sscanf(pFileData, "%255s %d%n", buffer, &nlevels, &cnt) != 2)
+ {
+ debug(LOG_ERROR, "iV_ProcessIMD %s bad levels info: %s", pFileName, buffer);
+ return NULL;
+ }
+ pFileData += cnt;
+ }
+
if (strncmp(buffer, "LEVELS", 6) != 0)
{
debug(LOG_ERROR, "iV_ProcessIMD: expecting 'LEVELS' directive (%s)", buffer);
@@ -865,6 +890,8 @@ iIMDShape *iV_ProcessIMD( const char **ppFileData, const char *FileDataEnd )
return NULL;
}
+ shape->shaderProgram = shader;
+
// load texture page if specified
if (bTextured)
{
@@ -120,6 +120,7 @@ struct iIMDShape
// The new rendering data
GLuint buffers[VBO_COUNT];
+ GLuint shaderProgram; // if using specialized shader for this model
iIMDShape *next; // next pie in multilevel pies (NULL for non multilevel !)
};
@@ -217,7 +217,14 @@ static void pie_Draw3DShape2(iIMDShape *shape, int frame, PIELIGHT colour, PIELI
if (light)
{
- pie_ActivateShader(SHADER_COMPONENT, shape, teamcolour, colour);
+ if (shape->shaderProgram)
+ {
+ pie_ActivateShader(shape->shaderProgram, shape, teamcolour, colour);
+ }
+ else
+ {
+ pie_ActivateShader(SHADER_COMPONENT, shape, teamcolour, colour);
+ }
}
else
{
@@ -214,16 +214,28 @@ static void getLocs(SHADER_PROGRAM *program)
glUniform1i(locTex3, 3);
}
+void pie_FreeShaders()
+{
+ while (shaderProgram.size() > SHADER_MAX)
+ {
+ SHADER_PROGRAM program = shaderProgram.takeLast();
+ glDeleteShader(program.program);
+ }
+}
+
// Read/compile/link shaders
-bool pie_LoadShader(SHADER_PROGRAM *program, const char *definitions, const char *vertexPath, const char *fragmentPath)
+GLuint pie_LoadShader(const char *definitions, const char *vertexPath, const char *fragmentPath)
{
+ SHADER_PROGRAM program;
GLint status;
bool success = true; // Assume overall success
char *buffer[2];
- program->program = glCreateProgram();
+ memset(&program, 0, sizeof(program));
+
+ program.program = glCreateProgram();
ASSERT_OR_RETURN(false, definitions != NULL, "Null in preprocessor definitions!");
- ASSERT_OR_RETURN(false, program->program, "Could not create shader program!");
+ ASSERT_OR_RETURN(false, program.program, "Could not create shader program!");
*buffer = (char *)definitions;
@@ -248,7 +260,7 @@ bool pie_LoadShader(SHADER_PROGRAM *program, const char *definitions, const char
else
{
printShaderInfoLog(LOG_3D, shader);
- glAttachShader(program->program, shader);
+ glAttachShader(program.program, shader);
success = true;
}
@@ -277,7 +289,7 @@ bool pie_LoadShader(SHADER_PROGRAM *program, const char *definitions, const char
else
{
printShaderInfoLog(LOG_3D, shader);
- glAttachShader(program->program, shader);
+ glAttachShader(program.program, shader);
success = true;
}
@@ -287,49 +299,49 @@ bool pie_LoadShader(SHADER_PROGRAM *program, const char *definitions, const char
if (success)
{
- glLinkProgram(program->program);
+ glLinkProgram(program.program);
// Check for linkage errors
- glGetProgramiv(program->program, GL_LINK_STATUS, &status);
+ glGetProgramiv(program.program, GL_LINK_STATUS, &status);
if (!status)
{
debug(LOG_ERROR, "Shader program linkage has failed [%s, %s]", vertexPath, fragmentPath);
- printProgramInfoLog(LOG_ERROR, program->program);
+ printProgramInfoLog(LOG_ERROR, program.program);
success = false;
}
else
{
- printProgramInfoLog(LOG_3D, program->program);
+ printProgramInfoLog(LOG_3D, program.program);
}
}
- getLocs(program);
+ getLocs(&program);
glUseProgram(0);
- return success;
+ shaderProgram.append(program);
+
+ return shaderProgram.size() - 1;
}
// Run from screen.c on init. Do not change the order of loading here! First ones are enumerated.
bool pie_LoadShaders()
{
- bool result;
SHADER_PROGRAM program;
+ int result;
// Load some basic shaders
memset(&program, 0, sizeof(program));
shaderProgram.append(program);
// TCMask shader for map-placed models with advanced lighting
debug(LOG_3D, "Loading shader: SHADER_COMPONENT");
- result = pie_LoadShader(&program, "", "shaders/tcmask.vert", "shaders/tcmask.frag");
+ result = pie_LoadShader("", "shaders/tcmask.vert", "shaders/tcmask.frag");
ASSERT_OR_RETURN(false, result, "Failed to load component shader");
- shaderProgram.append(program);
// TCMask shader for buttons with flat lighting
debug(LOG_3D, "Loading shader: SHADER_BUTTON");
- result = pie_LoadShader(&program, "", "shaders/button.vert", "shaders/button.frag");
+ result = pie_LoadShader("", "shaders/button.vert", "shaders/button.frag");
ASSERT_OR_RETURN(false, result, "Failed to load button shader");
- shaderProgram.append(program);
currentShaderMode = SHADER_NONE;
return true;
@@ -377,7 +389,7 @@ void pie_ActivateShader(int shaderMode, iIMDShape* shape, PIELIGHT teamcolour, P
glUniform1i(program.locFog, rendStates.fog);
glUniform1f(program.locTime, timeState);
- currentShaderMode = shaderMode;
+ currentShaderMode = shaderMode;
}
glColor4ubv(colour.vector);
@@ -85,7 +85,8 @@ extern void pie_SetAlphaTest(bool keyingOn);
extern void pie_SetRendMode(REND_MODE rendMode);
bool pie_LoadShaders();
-bool pie_LoadShader(SHADER_PROGRAM *program, const char *definitions, const char *vertexPath, const char *fragmentPath);
+void pie_FreeShaders();
+GLuint pie_LoadShader(const char *definitions, const char *vertexPath, const char *fragmentPath);
// Actual shaders (we do not want to export these calls)
void pie_ActivateShader(int shaderMode, iIMDShape* shape, PIELIGHT teamcolour, PIELIGHT colour);
View
@@ -934,6 +934,8 @@ bool stageOneShutDown(void)
{
debug(LOG_WZ, "== stageOneShutDown ==");
+ pie_FreeShaders();
+
if ( audio_Disabled() == false )
{
sound_CheckAllUnloaded();

0 comments on commit 465894d

Please sign in to comment.