Kaynağa Gözat

shader: support most standard parameters in the shader patcher.

legacy
Sam Hocevar sam 13 yıl önce
ebeveyn
işleme
c4511d9b8d
1 değiştirilmiş dosya ile 92 ekleme ve 28 silme
  1. +92
    -28
      src/shader.cpp

+ 92
- 28
src/shader.cpp Dosyayı Görüntüle

@@ -82,33 +82,40 @@ void Shader::Destroy(Shader *shader)
Shader::Shader(char const *vert, char const *frag)
: data(new ShaderData())
{
char buf[4096];
char buf[4096], errbuf[4096];
char const *shader = buf;
GLsizei len;

#if !defined __CELLOS_LV2__

/* Compile vertex shader and fragment shader */
/* Compile vertex shader */
ShaderData::Patch(buf, vert);
data->vert_crc = Hash::Crc32(buf);
data->vert_id = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(data->vert_id, 1, &shader, NULL);
glCompileShader(data->vert_id);

glGetShaderInfoLog(data->vert_id, sizeof(buf), &len, buf);
glGetShaderInfoLog(data->vert_id, sizeof(errbuf), &len, errbuf);
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);
data->frag_crc = Hash::Crc32(buf);
data->frag_id = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(data->frag_id, 1, &shader, NULL);
glCompileShader(data->frag_id);

glGetShaderInfoLog(data->frag_id, sizeof(buf), &len, buf);
glGetShaderInfoLog(data->frag_id, sizeof(errbuf), &len, errbuf);
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();
glAttachShader(data->prog_id, data->vert_id);
glAttachShader(data->prog_id, data->frag_id);
@@ -213,42 +220,99 @@ void ShaderData::Patch(char *dst, char const *src)
{
int version = GetVersion();

strcpy(dst, src);
if (version >= 130)
{
strcpy(dst, src);
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
};

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]);
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';
}
}



Yükleniyor…
İptal
Kaydet