pass vertex data between shader stages in a struct

This commit is contained in:
espes 2015-08-10 10:42:46 -07:00
parent 27cf9cd4da
commit 1a7a9534ab
6 changed files with 126 additions and 147 deletions

View File

@ -32,6 +32,7 @@
#include "qapi/qmp/qstring.h" #include "qapi/qmp/qstring.h"
#include "hw/xbox/nv2a_shaders_common.h"
#include "hw/xbox/nv2a_psh.h" #include "hw/xbox/nv2a_psh.h"
/* /*
@ -532,33 +533,24 @@ static QString* psh_convert(struct PixelShader *ps)
int i; int i;
QString *preflight = qstring_new(); QString *preflight = qstring_new();
qstring_append(preflight, "noperspective in vec4 gD0;\n"); qstring_append(preflight, STRUCT_VERTEX_DATA);
qstring_append(preflight, "noperspective in vec4 gD1;\n"); qstring_append(preflight, "noperspective in VertexData g_vtx;\n");
qstring_append(preflight, "noperspective in vec4 gB0;\n"); qstring_append(preflight, "#define vtx g_vtx\n");
qstring_append(preflight, "noperspective in vec4 gB1;\n");
qstring_append(preflight, "noperspective in vec4 gFog;\n");
qstring_append(preflight, "noperspective in vec4 gT0;\n");
qstring_append(preflight, "noperspective in vec4 gT1;\n");
qstring_append(preflight, "noperspective in vec4 gT2;\n");
qstring_append(preflight, "noperspective in vec4 gT3;\n");
qstring_append(preflight, "\n");
qstring_append(preflight, "noperspective in float gPos_w;\n");
qstring_append(preflight, "\n"); qstring_append(preflight, "\n");
qstring_append(preflight, "out vec4 fragColor;\n"); qstring_append(preflight, "out vec4 fragColor;\n");
qstring_append(preflight, "\n"); qstring_append(preflight, "\n");
/* calculate perspective-correct inputs */ /* calculate perspective-correct inputs */
QString *vars = qstring_new(); QString *vars = qstring_new();
qstring_append(vars, "float pFactor = gPos_w;\n"); qstring_append(vars, "vec4 pD0 = vtx.D0 / vtx.inv_w;\n");
qstring_append(vars, "vec4 pD0 = gD0 / pFactor;\n"); qstring_append(vars, "vec4 pD1 = vtx.D1 / vtx.inv_w;\n");
qstring_append(vars, "vec4 pD1 = gD1 / pFactor;\n"); qstring_append(vars, "vec4 pB0 = vtx.B0 / vtx.inv_w;\n");
qstring_append(vars, "vec4 pB0 = gB0 / pFactor;\n"); qstring_append(vars, "vec4 pB1 = vtx.B1 / vtx.inv_w;\n");
qstring_append(vars, "vec4 pB1 = gB1 / pFactor;\n"); qstring_append(vars, "vec4 pFog = vtx.Fog / vtx.inv_w;\n");
qstring_append(vars, "vec4 pFog = gFog / pFactor;\n"); qstring_append(vars, "vec4 pT0 = vtx.T0 / vtx.inv_w;\n");
qstring_append(vars, "vec4 pT0 = gT0 / pFactor;\n"); qstring_append(vars, "vec4 pT1 = vtx.T1 / vtx.inv_w;\n");
qstring_append(vars, "vec4 pT1 = gT1 / pFactor;\n"); qstring_append(vars, "vec4 pT2 = vtx.T2 / vtx.inv_w;\n");
qstring_append(vars, "vec4 pT2 = gT2 / pFactor;\n"); qstring_append(vars, "vec4 pT3 = vtx.T3 / vtx.inv_w;\n");
qstring_append(vars, "vec4 pT3 = gT3 / pFactor;\n");
qstring_append(vars, "\n"); qstring_append(vars, "\n");
qstring_append(vars, "vec4 v0 = pD0;\n"); qstring_append(vars, "vec4 v0 = pD0;\n");
qstring_append(vars, "vec4 v1 = pD1;\n"); qstring_append(vars, "vec4 v1 = pD1;\n");

View File

@ -19,9 +19,10 @@
*/ */
#include "qemu-common.h" #include "qemu-common.h"
#include "hw/xbox/nv2a_shaders_common.h"
#include "hw/xbox/nv2a_shaders.h" #include "hw/xbox/nv2a_shaders.h"
// #define DEBUG #define DEBUG
#ifdef DEBUG #ifdef DEBUG
# define NV2A_DPRINTF(format, ...) printf("nv2a: " format, ## __VA_ARGS__) # define NV2A_DPRINTF(format, ...) printf("nv2a: " format, ## __VA_ARGS__)
#else #else
@ -30,17 +31,9 @@
static void generate_geometry_shader_pass_vertex(QString* s, const char* v) static void generate_geometry_shader_pass_vertex(QString* s, const char* v)
{ {
qstring_append_fmt(s, " gD0 = vD0[%s];\n", v);
qstring_append_fmt(s, " gD1 = vD1[%s];\n", v);
qstring_append_fmt(s, " gB0 = vB0[%s];\n", v);
qstring_append_fmt(s, " gB1 = vB1[%s];\n", v);
qstring_append_fmt(s, " gFog = vFog[%s];\n", v);
qstring_append_fmt(s, " gT0 = vT0[%s];\n", v);
qstring_append_fmt(s, " gT1 = vT1[%s];\n", v);
qstring_append_fmt(s, " gT2 = vT2[%s];\n", v);
qstring_append_fmt(s, " gT3 = vT3[%s];\n", v);
qstring_append_fmt(s, " gPos_w = vPos_w[%s];\n", v);
qstring_append_fmt(s, " gl_Position = gl_in[%s].gl_Position;\n", v); qstring_append_fmt(s, " gl_Position = gl_in[%s].gl_Position;\n", v);
qstring_append_fmt(s, " gl_PointSize = gl_in[%s].gl_PointSize;\n", v);
qstring_append_fmt(s, " g_vtx = v_vtx[%s];\n", v);
qstring_append(s, " EmitVertex();\n"); qstring_append(s, " EmitVertex();\n");
} }
@ -60,28 +53,13 @@ static QString* generate_geometry_shader(enum ShaderPrimitiveMode primitive_mode
break; break;
} }
qstring_append(s, "\n"); qstring_append(s, "\n");
qstring_append(s, "noperspective in float vPos_w[];\n"); qstring_append(s, STRUCT_VERTEX_DATA);
qstring_append(s, "noperspective in vec4 vD0[];\n"); qstring_append(s,
qstring_append(s, "noperspective in vec4 vD1[];\n"); "noperspective in VertexData v_vtx[];\n");
qstring_append(s, "noperspective in vec4 vB0[];\n"); qstring_append(s,
qstring_append(s, "noperspective in vec4 vB1[];\n"); "noperspective out VertexData g_vtx;\n");
qstring_append(s, "noperspective in vec4 vFog[];\n");
qstring_append(s, "noperspective in vec4 vT0[];\n");
qstring_append(s, "noperspective in vec4 vT1[];\n");
qstring_append(s, "noperspective in vec4 vT2[];\n");
qstring_append(s, "noperspective in vec4 vT3[];\n");
qstring_append(s, "\n");
qstring_append(s, "noperspective out float gPos_w;\n");
qstring_append(s, "noperspective out vec4 gD0;\n");
qstring_append(s, "noperspective out vec4 gD1;\n");
qstring_append(s, "noperspective out vec4 gB0;\n");
qstring_append(s, "noperspective out vec4 gB1;\n");
qstring_append(s, "noperspective out vec4 gFog;\n");
qstring_append(s, "noperspective out vec4 gT0;\n");
qstring_append(s, "noperspective out vec4 gT1;\n");
qstring_append(s, "noperspective out vec4 gT2;\n");
qstring_append(s, "noperspective out vec4 gT3;\n");
qstring_append(s, "\n"); qstring_append(s, "\n");
qstring_append(s, "void main() {\n"); qstring_append(s, "void main() {\n");
switch (primitive_mode) { switch (primitive_mode) {
case PRIM_TYPE_QUADS: case PRIM_TYPE_QUADS:
@ -102,13 +80,14 @@ static QString* generate_geometry_shader(enum ShaderPrimitiveMode primitive_mode
static QString* generate_fixed_function(const ShaderState state, char v_prefix) static QString* generate_fixed_function(const ShaderState state,
char out_prefix)
{ {
int i, j; int i, j;
/* generate vertex shader mimicking fixed function */ /* generate vertex shader mimicking fixed function */
QString* vertex_shader_code = qstring_new(); QString* s = qstring_new();
qstring_append(vertex_shader_code, qstring_append(s,
"#version 330\n" "#version 330\n"
"\n" "\n"
"in vec4 position;\n" "in vec4 position;\n"
@ -125,28 +104,11 @@ static QString* generate_fixed_function(const ShaderState state, char v_prefix)
"in vec4 texture3;\n" "in vec4 texture3;\n"
"\n"); "\n");
qstring_append_fmt(vertex_shader_code, qstring_append(s, STRUCT_VERTEX_DATA);
"noperspective out float %cPos_w;\n", v_prefix); qstring_append_fmt(s, "noperspective out VertexData %c_vtx;\n", out_prefix);
qstring_append_fmt(vertex_shader_code, qstring_append_fmt(s, "#define vtx %c_vtx", out_prefix);
"noperspective out vec4 %cD0 = vec4(0.0,0.0,0.0,1.0);\n", v_prefix);
qstring_append_fmt(vertex_shader_code,
"noperspective out vec4 %cD1 = vec4(0.0,0.0,0.0,1.0);\n", v_prefix);
qstring_append_fmt(vertex_shader_code,
"noperspective out vec4 %cB0 = vec4(0.0,0.0,0.0,1.0);\n", v_prefix);
qstring_append_fmt(vertex_shader_code,
"noperspective out vec4 %cB1 = vec4(0.0,0.0,0.0,1.0);\n", v_prefix);
qstring_append_fmt(vertex_shader_code,
"noperspective out vec4 %cFog = vec4(0.0,0.0,0.0,1.0);\n", v_prefix);
qstring_append_fmt(vertex_shader_code,
"noperspective out vec4 %cT0 = vec4(0.0,0.0,0.0,1.0);\n", v_prefix);
qstring_append_fmt(vertex_shader_code,
"noperspective out vec4 %cT1 = vec4(0.0,0.0,0.0,1.0);\n", v_prefix);
qstring_append_fmt(vertex_shader_code,
"noperspective out vec4 %cT2 = vec4(0.0,0.0,0.0,1.0);\n", v_prefix);
qstring_append_fmt(vertex_shader_code,
"noperspective out vec4 %cT3 = vec4(0.0,0.0,0.0,1.0);\n", v_prefix);
qstring_append(vertex_shader_code, qstring_append(s,
"\n" "\n"
/* FIXME: Add these uniforms using code when they are used */ /* FIXME: Add these uniforms using code when they are used */
"uniform mat4 texMat0;\n" "uniform mat4 texMat0;\n"
@ -189,19 +151,19 @@ static QString* generate_fixed_function(const ShaderState state, char v_prefix)
assert(false); assert(false);
break; break;
} }
qstring_append_fmt(vertex_shader_code, "/* Skinning mode %d */\n", qstring_append_fmt(s, "/* Skinning mode %d */\n",
state.skinning); state.skinning);
if (count == 0) { if (count == 0) {
qstring_append(vertex_shader_code, "vec4 tPosition = position * modelViewMat0;\n"); qstring_append(s, "vec4 tPosition = position * modelViewMat0;\n");
/* FIXME: Is the normal still transformed? */ /* FIXME: Is the normal still transformed? */
qstring_append(vertex_shader_code, "vec3 tNormal = (vec4(normal, 0.0) * invModelViewMat0).xyz;\n"); qstring_append(s, "vec3 tNormal = (vec4(normal, 0.0) * invModelViewMat0).xyz;\n");
} else { } else {
qstring_append(vertex_shader_code, "vec4 tPosition = vec4(0.0);\n"); qstring_append(s, "vec4 tPosition = vec4(0.0);\n");
qstring_append(vertex_shader_code, "vec3 tNormal = vec3(0.0);\n"); qstring_append(s, "vec3 tNormal = vec3(0.0);\n");
if (mix) { if (mix) {
/* Tweening */ /* Tweening */
if (count == 2) { if (count == 2) {
qstring_append(vertex_shader_code, qstring_append(s,
"tPosition += mix(position * modelViewMat1,\n" "tPosition += mix(position * modelViewMat1,\n"
" position * modelViewMat0, weight.x);\n" " position * modelViewMat0, weight.x);\n"
"tNormal += mix((vec4(normal, 0.0) * invModelViewMat1).xyz,\n" "tNormal += mix((vec4(normal, 0.0) * invModelViewMat1).xyz,\n"
@ -214,10 +176,10 @@ static QString* generate_fixed_function(const ShaderState state, char v_prefix)
/* Individual matrices */ /* Individual matrices */
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
char c = "xyzw"[i]; char c = "xyzw"[i];
qstring_append_fmt(vertex_shader_code, qstring_append_fmt(s,
"tPosition += position * modelViewMat%d * weight.%c;\n", "tPosition += position * modelViewMat%d * weight.%c;\n",
i, c); i, c);
qstring_append_fmt(vertex_shader_code, qstring_append_fmt(s,
"tNormal += (vec4(normal, 0.0) * invModelViewMat%d * weight.%c).xyz;\n", "tNormal += (vec4(normal, 0.0) * invModelViewMat%d * weight.%c).xyz;\n",
i, c); i, c);
} }
@ -227,14 +189,14 @@ static QString* generate_fixed_function(const ShaderState state, char v_prefix)
/* Normalization */ /* Normalization */
if (state.normalization) { if (state.normalization) {
qstring_append(vertex_shader_code, "tNormal = normalize(tNormal);\n"); qstring_append(s, "tNormal = normalize(tNormal);\n");
} }
/* Texgen */ /* Texgen */
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
qstring_append_fmt(vertex_shader_code, "/* Texgen for stage %d */\n", qstring_append_fmt(s, "/* Texgen for stage %d */\n",
i); i);
qstring_append_fmt(vertex_shader_code, "vec4 tTexture%d;\n", qstring_append_fmt(s, "vec4 tTexture%d;\n",
i); i);
/* Set each component individually */ /* Set each component individually */
/* FIXME: could be nicer if some channels share the same texgen */ /* FIXME: could be nicer if some channels share the same texgen */
@ -242,17 +204,17 @@ static QString* generate_fixed_function(const ShaderState state, char v_prefix)
char c = "xyzw"[j]; char c = "xyzw"[j];
switch (state.texgen[i][j]) { switch (state.texgen[i][j]) {
case TEXGEN_DISABLE: case TEXGEN_DISABLE:
qstring_append_fmt(vertex_shader_code, qstring_append_fmt(s,
"tTexture%d.%c = texture%d.%c;\n", "tTexture%d.%c = texture%d.%c;\n",
i, c, i, c); i, c, i, c);
break; break;
case TEXGEN_EYE_LINEAR: case TEXGEN_EYE_LINEAR:
qstring_append_fmt(vertex_shader_code, qstring_append_fmt(s,
"tTexture%d.%c = tPosition.%c;\n", "tTexture%d.%c = tPosition.%c;\n",
i, c, c); i, c, c);
break; break;
case TEXGEN_OBJECT_LINEAR: case TEXGEN_OBJECT_LINEAR:
qstring_append_fmt(vertex_shader_code, qstring_append_fmt(s,
"tTexture%d.%c = position.%c;\n", "tTexture%d.%c = position.%c;\n",
i, c, c); i, c, c);
break; break;
@ -262,14 +224,14 @@ static QString* generate_fixed_function(const ShaderState state, char v_prefix)
break; break;
case TEXGEN_REFLECTION_MAP: case TEXGEN_REFLECTION_MAP:
assert(i < 3); /* Channels S,T,R only! */ assert(i < 3); /* Channels S,T,R only! */
qstring_append_fmt(vertex_shader_code, qstring_append_fmt(s,
"tTexture%d.%c = reflect(???, tNormal).%c;\n", "tTexture%d.%c = reflect(???, tNormal).%c;\n",
i, c, c); i, c, c);
assert(false); /* FIXME: Code not complete yet! */ assert(false); /* FIXME: Code not complete yet! */
break; break;
case TEXGEN_NORMAL_MAP: case TEXGEN_NORMAL_MAP:
assert(i < 3); /* Channels S,T,R only! */ assert(i < 3); /* Channels S,T,R only! */
qstring_append_fmt(vertex_shader_code, qstring_append_fmt(s,
"tTexture%d.%c = tNormal.%c;\n", "tTexture%d.%c = tNormal.%c;\n",
i, c, c); i, c, c);
break; break;
@ -283,7 +245,7 @@ static QString* generate_fixed_function(const ShaderState state, char v_prefix)
/* Apply texture matrices */ /* Apply texture matrices */
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
if (state.texture_matrix_enable[i]) { if (state.texture_matrix_enable[i]) {
qstring_append_fmt(vertex_shader_code, qstring_append_fmt(s,
"tTexture%d = tTexture%d * texMat%d;\n", "tTexture%d = tTexture%d * texMat%d;\n",
i, i, i); i, i, i);
} }
@ -291,10 +253,10 @@ static QString* generate_fixed_function(const ShaderState state, char v_prefix)
/* If skinning is off the composite matrix already includes the MV matrix */ /* If skinning is off the composite matrix already includes the MV matrix */
if (state.skinning == SKINNING_OFF) { if (state.skinning == SKINNING_OFF) {
qstring_append(vertex_shader_code, "tPosition = position;\n"); qstring_append(s, "tPosition = position;\n");
} }
qstring_append(vertex_shader_code, qstring_append(s,
" gl_Position = invViewport * (tPosition * compositeMat);\n" " gl_Position = invViewport * (tPosition * compositeMat);\n"
/* temp hack: the composite matrix includes the view transform... */ /* temp hack: the composite matrix includes the view transform... */
//" gl_Position = position * compositeMat;\n" //" gl_Position = position * compositeMat;\n"
@ -302,28 +264,20 @@ static QString* generate_fixed_function(const ShaderState state, char v_prefix)
//" gl_Position.y = -(gl_Position.y - 240.0) / 240.0;\n" //" gl_Position.y = -(gl_Position.y - 240.0) / 240.0;\n"
" gl_Position.z = gl_Position.z * 2.0 - gl_Position.w;\n"); " gl_Position.z = gl_Position.z * 2.0 - gl_Position.w;\n");
qstring_append_fmt(vertex_shader_code, qstring_append(s, "vtx.inv_w = 1.0/gl_Position.w;\n");
"%cPos_w = 1.0/gl_Position.w;\n", v_prefix); qstring_append(s, "vtx.D0 = diffuse * vtx.inv_w;\n");
qstring_append_fmt(vertex_shader_code, qstring_append(s, "vtx.D1 = specular * vtx.inv_w;\n");
"%cD0 = diffuse * %cPos_w;\n", v_prefix, v_prefix); qstring_append(s, "vtx.B0 = backDiffuse * vtx.inv_w;\n");
qstring_append_fmt(vertex_shader_code, qstring_append(s, "vtx.B1 = backSpecular * vtx.inv_w;\n");
"%cD1 = specular * %cPos_w;\n", v_prefix, v_prefix); qstring_append(s, "vtx.Fog = vec4(0.0,0.0,0.0,1.0) * vtx.inv_w;\n");
qstring_append_fmt(vertex_shader_code, qstring_append(s, "vtx.T0 = tTexture0 * vtx.inv_w;\n");
"%cB0 = backDiffuse * %cPos_w;\n", v_prefix, v_prefix); qstring_append(s, "vtx.T1 = tTexture1 * vtx.inv_w;\n");
qstring_append_fmt(vertex_shader_code, qstring_append(s, "vtx.T2 = tTexture2 * vtx.inv_w;\n");
"%cB1 = backSpecular * %cPos_w;\n", v_prefix, v_prefix); qstring_append(s, "vtx.T3 = tTexture3 * vtx.inv_w;\n");
qstring_append_fmt(vertex_shader_code,
"%cT0 = tTexture0 * %cPos_w;\n", v_prefix, v_prefix);
qstring_append_fmt(vertex_shader_code,
"%cT1 = tTexture1 * %cPos_w;\n", v_prefix, v_prefix);
qstring_append_fmt(vertex_shader_code,
"%cT2 = tTexture2 * %cPos_w;\n", v_prefix, v_prefix);
qstring_append_fmt(vertex_shader_code,
"%cT3 = tTexture3 * %cPos_w;\n", v_prefix, v_prefix);
qstring_append(vertex_shader_code, "}\n"); qstring_append(s, "}\n");
return vertex_shader_code; return s;
} }
ShaderBinding* generate_shaders(const ShaderState state) ShaderBinding* generate_shaders(const ShaderState state)
@ -332,7 +286,7 @@ ShaderBinding* generate_shaders(const ShaderState state)
GLint compiled = 0; GLint compiled = 0;
bool with_geom = state.primitive_mode == PRIM_TYPE_QUADS; bool with_geom = state.primitive_mode == PRIM_TYPE_QUADS;
char v_prefix = with_geom ? 'v' : 'g'; char vtx_prefix = with_geom ? 'v' : 'g';
GLuint program = glCreateProgram(); GLuint program = glCreateProgram();
@ -340,13 +294,13 @@ ShaderBinding* generate_shaders(const ShaderState state)
QString *vertex_shader_code = NULL; QString *vertex_shader_code = NULL;
if (state.fixed_function) { if (state.fixed_function) {
vertex_shader_code = generate_fixed_function(state, v_prefix); vertex_shader_code = generate_fixed_function(state, vtx_prefix);
} else if (state.vertex_program) { } else if (state.vertex_program) {
vertex_shader_code = vsh_translate(VSH_VERSION_XVS, vertex_shader_code = vsh_translate(VSH_VERSION_XVS,
(uint32_t*)state.program_data, (uint32_t*)state.program_data,
state.program_length, state.program_length,
v_prefix); vtx_prefix);
} else { } else {
assert(false); assert(false);
} }
@ -520,4 +474,4 @@ ShaderBinding* generate_shaders(const ShaderState state)
} }
return ret; return ret;
} }

View File

@ -18,6 +18,9 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>. * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef HW_NV2A_SHADERS_H
#define HW_NV2A_SHADERS_H
#include "qapi/qmp/qstring.h" #include "qapi/qmp/qstring.h"
#include "gl/gloffscreen.h" #include "gl/gloffscreen.h"
@ -102,3 +105,4 @@ typedef struct ShaderBinding {
ShaderBinding* generate_shaders(const ShaderState state); ShaderBinding* generate_shaders(const ShaderState state);
#endif

View File

@ -0,0 +1,37 @@
/*
* QEMU Geforce NV2A shader common definitions
*
* Copyright (c) 2015 espes
* Copyright (c) 2015 JayFoxRox
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 or
* (at your option) version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef HW_NV2A_SHADERS_COMMON_H
#define HW_NV2A_SHADERS_COMMON_H
#define STRUCT_VERTEX_DATA "struct VertexData {\n" \
" float inv_w;\n" \
" vec4 D0;\n" \
" vec4 D1;\n" \
" vec4 B0;\n" \
" vec4 B1;\n" \
" vec4 Fog;\n" \
" vec4 T0;\n" \
" vec4 T1;\n" \
" vec4 T2;\n" \
" vec4 T3;\n" \
"};\n"
#endif

View File

@ -30,6 +30,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <assert.h> #include <assert.h>
#include "hw/xbox/nv2a_shaders_common.h"
#include "hw/xbox/nv2a_vsh.h" #include "hw/xbox/nv2a_vsh.h"
#define VSH_D3DSCM_CORRECTION 96 #define VSH_D3DSCM_CORRECTION 96
@ -733,21 +734,13 @@ static const char* vsh_header =
QString* vsh_translate(uint16_t version, QString* vsh_translate(uint16_t version,
const uint32_t *tokens, const uint32_t *tokens,
unsigned int length, unsigned int length,
char output_prefix) char out_prefix)
{ {
QString* header = qstring_from_str("#version 330\n\n"); QString* header = qstring_from_str("#version 330\n\n");
qstring_append(header, STRUCT_VERTEX_DATA);
qstring_append_fmt(header, "noperspective out float %cPos_w;\n", output_prefix); qstring_append_fmt(header, "noperspective out VertexData %c_vtx;\n", out_prefix);
qstring_append_fmt(header, "noperspective out vec4 %cD0;\n", output_prefix); qstring_append_fmt(header, "#define vtx %c_vtx", out_prefix);
qstring_append_fmt(header, "noperspective out vec4 %cD1;\n", output_prefix);
qstring_append_fmt(header, "noperspective out vec4 %cB0;\n", output_prefix);
qstring_append_fmt(header, "noperspective out vec4 %cB1;\n", output_prefix);
qstring_append_fmt(header, "noperspective out vec4 %cFog;\n", output_prefix);
qstring_append_fmt(header, "noperspective out vec4 %cT0;\n", output_prefix);
qstring_append_fmt(header, "noperspective out vec4 %cT1;\n", output_prefix);
qstring_append_fmt(header, "noperspective out vec4 %cT2;\n", output_prefix);
qstring_append_fmt(header, "noperspective out vec4 %cT3;\n", output_prefix);
qstring_append(header, "\n" qstring_append(header, "\n"
"uniform mat4 texMat0;\n" "uniform mat4 texMat0;\n"
"uniform mat4 texMat1;\n" "uniform mat4 texMat1;\n"
@ -780,22 +773,21 @@ QString* vsh_translate(uint16_t version,
/* pre-divide and output the generated W so we can do persepctive correct /* pre-divide and output the generated W so we can do persepctive correct
* interpolation manually. OpenGL can't, since we give it a W of 1 to work * interpolation manually. OpenGL can't, since we give it a W of 1 to work
* around the perspective divide */ * around the perspective divide */
qstring_append_fmt(body, qstring_append(body,
"if (oPos.w == 0.0 || isinf(oPos.w)) {\n" "if (oPos.w == 0.0 || isinf(oPos.w)) {\n"
" %cPos_w = 1.0;" " vtx.inv_w = 1.0;"
"} else {\n" "} else {\n"
" %cPos_w = 1.0 / oPos.w;\n" " vtx.inv_w = 1.0 / oPos.w;\n"
"}\n" "}\n");
, output_prefix, output_prefix); qstring_append(body, "vtx.D0 = clamp(oD0, 0.0, 1.0) * vtx.inv_w;\n");
qstring_append_fmt(body, "%cD0 = clamp(oD0, 0.0, 1.0) * %cPos_w;\n", output_prefix, output_prefix); qstring_append(body, "vtx.D1 = clamp(oD1, 0.0, 1.0) * vtx.inv_w;\n");
qstring_append_fmt(body, "%cD1 = clamp(oD1, 0.0, 1.0) * %cPos_w;\n", output_prefix, output_prefix); qstring_append(body, "vtx.B0 = clamp(oB0, 0.0, 1.0) * vtx.inv_w;\n");
qstring_append_fmt(body, "%cB0 = clamp(oB0, 0.0, 1.0) * %cPos_w;\n", output_prefix, output_prefix); qstring_append(body, "vtx.B1 = clamp(oB1, 0.0, 1.0) * vtx.inv_w;\n");
qstring_append_fmt(body, "%cB1 = clamp(oB1, 0.0, 1.0) * %cPos_w;\n", output_prefix, output_prefix); qstring_append(body, "vtx.Fog = oFog * vtx.inv_w;\n");
qstring_append_fmt(body, "%cFog = oFog * %cPos_w;\n", output_prefix, output_prefix); qstring_append(body, "vtx.T0 = oT0 * vtx.inv_w;\n");
qstring_append_fmt(body, "%cT0 = oT0 * %cPos_w;\n", output_prefix, output_prefix); qstring_append(body, "vtx.T1 = oT1 * vtx.inv_w;\n");
qstring_append_fmt(body, "%cT1 = oT1 * %cPos_w;\n", output_prefix, output_prefix); qstring_append(body, "vtx.T2 = oT2 * vtx.inv_w;\n");
qstring_append_fmt(body, "%cT2 = oT2 * %cPos_w;\n", output_prefix, output_prefix); qstring_append(body, "vtx.T3 = oT3 * vtx.inv_w;\n");
qstring_append_fmt(body, "%cT3 = oT3 * %cPos_w;\n", output_prefix, output_prefix);
qstring_append(body, qstring_append(body,
/* the shaders leave the result in screen space, while /* the shaders leave the result in screen space, while

View File

@ -106,7 +106,7 @@ uint8_t vsh_get_field(const uint32_t *shader_token, VshFieldName field_name);
QString* vsh_translate(uint16_t version, QString* vsh_translate(uint16_t version,
const uint32_t *tokens, const uint32_t *tokens,
unsigned int length, unsigned int length,
char output_prefix); char out_prefix);
#endif #endif