|
@@ -82,33 +82,40 @@ void Shader::Destroy(Shader *shader) |
|
|
Shader::Shader(char const *vert, char const *frag) |
|
|
Shader::Shader(char const *vert, char const *frag) |
|
|
: data(new ShaderData()) |
|
|
: data(new ShaderData()) |
|
|
{ |
|
|
{ |
|
|
char buf[4096]; |
|
|
|
|
|
|
|
|
char buf[4096], errbuf[4096]; |
|
|
char const *shader = buf; |
|
|
char const *shader = buf; |
|
|
GLsizei len; |
|
|
GLsizei len; |
|
|
|
|
|
|
|
|
#if !defined __CELLOS_LV2__ |
|
|
#if !defined __CELLOS_LV2__ |
|
|
|
|
|
|
|
|
/* Compile vertex shader and fragment shader */ |
|
|
|
|
|
|
|
|
/* Compile vertex shader */ |
|
|
ShaderData::Patch(buf, vert); |
|
|
ShaderData::Patch(buf, vert); |
|
|
data->vert_crc = Hash::Crc32(buf); |
|
|
data->vert_crc = Hash::Crc32(buf); |
|
|
data->vert_id = glCreateShader(GL_VERTEX_SHADER); |
|
|
data->vert_id = glCreateShader(GL_VERTEX_SHADER); |
|
|
glShaderSource(data->vert_id, 1, &shader, NULL); |
|
|
glShaderSource(data->vert_id, 1, &shader, NULL); |
|
|
glCompileShader(data->vert_id); |
|
|
glCompileShader(data->vert_id); |
|
|
|
|
|
|
|
|
glGetShaderInfoLog(data->vert_id, sizeof(buf), &len, buf); |
|
|
|
|
|
|
|
|
glGetShaderInfoLog(data->vert_id, sizeof(errbuf), &len, errbuf); |
|
|
if (len > 0) |
|
|
if (len > 0) |
|
|
Log::Error("failed to compile vertex shader: %s", buf); |
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
Log::Error("failed to compile vertex shader: %s", errbuf); |
|
|
|
|
|
Log::Error("shader source:\n%s\n", buf); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Compile fragment shader */ |
|
|
ShaderData::Patch(buf, frag); |
|
|
ShaderData::Patch(buf, frag); |
|
|
data->frag_crc = Hash::Crc32(buf); |
|
|
data->frag_crc = Hash::Crc32(buf); |
|
|
data->frag_id = glCreateShader(GL_FRAGMENT_SHADER); |
|
|
data->frag_id = glCreateShader(GL_FRAGMENT_SHADER); |
|
|
glShaderSource(data->frag_id, 1, &shader, NULL); |
|
|
glShaderSource(data->frag_id, 1, &shader, NULL); |
|
|
glCompileShader(data->frag_id); |
|
|
glCompileShader(data->frag_id); |
|
|
|
|
|
|
|
|
glGetShaderInfoLog(data->frag_id, sizeof(buf), &len, buf); |
|
|
|
|
|
|
|
|
glGetShaderInfoLog(data->frag_id, sizeof(errbuf), &len, errbuf); |
|
|
if (len > 0) |
|
|
if (len > 0) |
|
|
Log::Error("failed to compile fragment shader: %s", buf); |
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
Log::Error("failed to compile fragment shader: %s", errbuf); |
|
|
|
|
|
Log::Error("shader source:\n%s\n", buf); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Create program */ |
|
|
data->prog_id = glCreateProgram(); |
|
|
data->prog_id = glCreateProgram(); |
|
|
glAttachShader(data->prog_id, data->vert_id); |
|
|
glAttachShader(data->prog_id, data->vert_id); |
|
|
glAttachShader(data->prog_id, data->frag_id); |
|
|
glAttachShader(data->prog_id, data->frag_id); |
|
@@ -213,42 +220,99 @@ void ShaderData::Patch(char *dst, char const *src) |
|
|
{ |
|
|
{ |
|
|
int version = GetVersion(); |
|
|
int version = GetVersion(); |
|
|
|
|
|
|
|
|
|
|
|
strcpy(dst, src); |
|
|
if (version >= 130) |
|
|
if (version >= 130) |
|
|
{ |
|
|
|
|
|
strcpy(dst, src); |
|
|
|
|
|
return; |
|
|
return; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (version == 120) |
|
|
|
|
|
|
|
|
if (version >= 110) |
|
|
{ |
|
|
{ |
|
|
static char const * const replaces[] = |
|
|
|
|
|
|
|
|
char *parser, *main; |
|
|
|
|
|
char const *end = dst + strlen(dst) + 1; |
|
|
|
|
|
|
|
|
|
|
|
/* Find main() */ |
|
|
|
|
|
parser = strstr(dst, "main"); |
|
|
|
|
|
if (!parser) return; |
|
|
|
|
|
parser = strstr(parser, "("); |
|
|
|
|
|
if (!parser) return; |
|
|
|
|
|
parser = strstr(parser, ")"); |
|
|
|
|
|
if (!parser) return; |
|
|
|
|
|
parser = strstr(parser, "{"); |
|
|
|
|
|
if (!parser) return; |
|
|
|
|
|
main = parser + 1; |
|
|
|
|
|
|
|
|
|
|
|
/* Perform main() replaces */ |
|
|
|
|
|
static char const * const main_replaces[] = |
|
|
{ |
|
|
{ |
|
|
"#version 130", "#version 120", |
|
|
|
|
|
"\nin vec2", "\nvec2", |
|
|
|
|
|
"\nin vec3", "\nvec3", |
|
|
|
|
|
"\nin vec4", "\nvec4", |
|
|
|
|
|
"\nin mat4", "\nmat4", |
|
|
|
|
|
|
|
|
"in vec2 in_Vertex;", "vec2 in_Vertex = gl_Vertex.xy;", |
|
|
|
|
|
"in vec3 in_Vertex;", "vec3 in_Vertex = gl_Vertex.xyz;", |
|
|
|
|
|
"in vec4 in_Vertex;", "vec4 in_Vertex = gl_Vertex.xyzw;", |
|
|
|
|
|
|
|
|
|
|
|
"in vec2 in_Color;", "vec2 in_Color = gl_Color.xy;", |
|
|
|
|
|
"in vec3 in_Color;", "vec3 in_Color = gl_Color.xyz;", |
|
|
|
|
|
"in vec4 in_Color;", "vec4 in_Color = gl_Color.xyzw;", |
|
|
|
|
|
|
|
|
|
|
|
"in vec2 in_MultiTexCoord0;", |
|
|
|
|
|
"vec2 in_MultiTexCoord0 = gl_MultiTexCoord0.xy;", |
|
|
|
|
|
"in vec2 in_MultiTexCoord1;", |
|
|
|
|
|
"vec2 in_MultiTexCoord1 = gl_MultiTexCoord1.xy;", |
|
|
|
|
|
"in vec2 in_MultiTexCoord2;", |
|
|
|
|
|
"vec2 in_MultiTexCoord2 = gl_MultiTexCoord2.xy;", |
|
|
|
|
|
"in vec2 in_MultiTexCoord3;", |
|
|
|
|
|
"vec2 in_MultiTexCoord3 = gl_MultiTexCoord3.xy;", |
|
|
|
|
|
"in vec2 in_MultiTexCoord4;", |
|
|
|
|
|
"vec2 in_MultiTexCoord4 = gl_MultiTexCoord4.xy;", |
|
|
|
|
|
"in vec2 in_MultiTexCoord5;", |
|
|
|
|
|
"vec2 in_MultiTexCoord5 = gl_MultiTexCoord5.xy;", |
|
|
|
|
|
"in vec2 in_MultiTexCoord6;", |
|
|
|
|
|
"vec2 in_MultiTexCoord6 = gl_MultiTexCoord6.xy;", |
|
|
|
|
|
"in vec2 in_MultiTexCoord7;", |
|
|
|
|
|
"vec2 in_MultiTexCoord7 = gl_MultiTexCoord7.xy;", |
|
|
|
|
|
|
|
|
NULL |
|
|
NULL |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
while (*src) |
|
|
|
|
|
|
|
|
for (char const * const *rep = main_replaces; rep[0]; rep += 2) |
|
|
{ |
|
|
{ |
|
|
for (char const * const *rep = replaces; rep[0]; rep += 2) |
|
|
|
|
|
|
|
|
char *match = strstr(dst, rep[0]); |
|
|
|
|
|
if (match && match < main) |
|
|
{ |
|
|
{ |
|
|
size_t l0 = strlen(rep[0]); |
|
|
size_t l0 = strlen(rep[0]); |
|
|
if (!strncmp(src, rep[0], l0)) |
|
|
|
|
|
{ |
|
|
|
|
|
src += l0; |
|
|
|
|
|
dst += sprintf(dst, "%s", rep[1]); |
|
|
|
|
|
goto next; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
size_t l1 = strlen(rep[1]); |
|
|
|
|
|
memmove(main + l1, main, end - main); |
|
|
|
|
|
memcpy(main, rep[1], l1); |
|
|
|
|
|
memset(match, ' ', l0); |
|
|
|
|
|
main += l1; |
|
|
|
|
|
end += l1; |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
*dst++ = *src++; |
|
|
|
|
|
|
|
|
/* Perform small replaces */ |
|
|
|
|
|
static char const * const fast_replaces[] = |
|
|
|
|
|
{ |
|
|
|
|
|
"#version 130", "#version 120", |
|
|
|
|
|
"\nin vec2", "\n vec2", |
|
|
|
|
|
"\nin vec3", "\n vec3", |
|
|
|
|
|
"\nin vec4", "\n vec4", |
|
|
|
|
|
"\nin mat4", "\n mat4", |
|
|
|
|
|
NULL |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
next: continue; |
|
|
|
|
|
|
|
|
for (char const * const *rep = fast_replaces; rep[0]; rep += 2) |
|
|
|
|
|
{ |
|
|
|
|
|
char *match; |
|
|
|
|
|
while ((match = strstr(dst, rep[0]))) |
|
|
|
|
|
{ |
|
|
|
|
|
size_t l0 = strlen(rep[0]); |
|
|
|
|
|
size_t l1 = strlen(rep[1]); |
|
|
|
|
|
|
|
|
|
|
|
if (l1 > l0) |
|
|
|
|
|
memmove(match + l1, match + l0, (end - match) - l0); |
|
|
|
|
|
memcpy(match, rep[1], l1); |
|
|
|
|
|
if (l1 < l0) |
|
|
|
|
|
memset(match + l0, ' ', l1 - l0); |
|
|
|
|
|
end += l1 - l0; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
*dst = '\0'; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|