mirror of https://github.com/PCSX2/pcsx2.git
zzogl: GLSL is working again for AMD gpu. Nvidia test is welcome
* properly release shader in release mode * set stream format every time an array buffer is bound git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5219 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
2db7ddaaa3
commit
cdeaa5e03c
|
@ -165,10 +165,14 @@ class GSVertexBufferStateOGL {
|
|||
GLuint m_va;
|
||||
GLenum m_topology;
|
||||
|
||||
// DEBUG
|
||||
vector<GSInputLayoutOGL> layout_store;
|
||||
|
||||
public:
|
||||
GSVertexBufferStateOGL(size_t stride, GSInputLayoutOGL* layout, uint32 layout_nbr)
|
||||
{
|
||||
glGenVertexArrays(1, &m_va);
|
||||
layout_store.clear();
|
||||
|
||||
m_vb = new GSBufferOGL(GL_ARRAY_BUFFER, stride);
|
||||
m_ib = new GSBufferOGL(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint32));
|
||||
|
@ -188,24 +192,40 @@ public:
|
|||
m_vb->bind();
|
||||
}
|
||||
|
||||
void set_internal_format(GSInputLayoutOGL* layout, uint32 layout_nbr)
|
||||
void set_internal_format()
|
||||
{
|
||||
for (uint i = 0; i < layout_nbr; i++) {
|
||||
for (vector<GSInputLayoutOGL>::iterator it = layout_store.begin(); it != layout_store.end(); it++)
|
||||
set_internal_format(*it);
|
||||
}
|
||||
|
||||
void set_internal_format(GSInputLayoutOGL& layout) {
|
||||
// Note this function need both a vertex array object and a GL_ARRAY_BUFFER buffer
|
||||
glEnableVertexAttribArray(layout[i].index);
|
||||
switch (layout[i].type) {
|
||||
glEnableVertexAttribArray(layout.index);
|
||||
switch (layout.type) {
|
||||
case GL_UNSIGNED_SHORT:
|
||||
case GL_UNSIGNED_INT:
|
||||
case GL_SHORT:
|
||||
case GL_INT:
|
||||
// Rule: when shader use integral (not normalized) you must use glVertexAttribIPointer (note the extra I)
|
||||
glVertexAttribIPointer(layout[i].index, layout[i].size, layout[i].type, layout[i].stride, layout[i].offset);
|
||||
if (layout.normalize == false)
|
||||
glVertexAttribIPointer(layout.index, layout.size, layout.type, layout.stride, layout.offset);
|
||||
else
|
||||
glVertexAttribPointer(layout.index, layout.size, layout.type, layout.normalize, layout.stride, layout.offset);
|
||||
break;
|
||||
default:
|
||||
glVertexAttribPointer(layout[i].index, layout[i].size, layout[i].type, layout[i].normalize, layout[i].stride, layout[i].offset);
|
||||
glVertexAttribPointer(layout.index, layout.size, layout.type, layout.normalize, layout.stride, layout.offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void set_internal_format(GSInputLayoutOGL* layout, uint32 layout_nbr)
|
||||
{
|
||||
for (uint i = 0; i < layout_nbr; i++) {
|
||||
// DEBUG
|
||||
layout_store.push_back(layout[i]);
|
||||
|
||||
set_internal_format(layout[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void EndScene()
|
||||
|
|
|
@ -84,6 +84,9 @@ static __forceinline void GL_STENCILFUNC_SET()
|
|||
glStencilFunc(s_stencilfunc, s_stencilref, s_stencilmask);
|
||||
}
|
||||
|
||||
#ifdef GLSL4_API
|
||||
#include "ZZoglShaders.h"
|
||||
#endif
|
||||
// sets the data stream
|
||||
static __forceinline void SET_STREAM()
|
||||
{
|
||||
|
@ -92,6 +95,8 @@ static __forceinline void SET_STREAM()
|
|||
glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, sizeof(VertexGPU), (void*)12);
|
||||
glTexCoordPointer(3, GL_FLOAT, sizeof(VertexGPU), (void*)16);
|
||||
glVertexPointer(4, GL_SHORT, sizeof(VertexGPU), (void*)0);
|
||||
#else
|
||||
vertex_array->set_internal_format();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@ typedef void (APIENTRYP _PFNSWAPINTERVAL)(int);
|
|||
|
||||
map<string, GLbyte> mapGLExtensions;
|
||||
|
||||
extern bool LoadEffects();
|
||||
extern bool ZZshLoadExtraEffects();
|
||||
extern FRAGMENTSHADER* ZZshLoadShadeEffect(int type, int texfilter, int fog, int testaem, int exactcolor, const clampInfo& clamp, int context, bool* pbFailed);
|
||||
|
||||
|
@ -575,10 +574,9 @@ bool ZZCreate(int _width, int _height)
|
|||
GL_REPORT_ERROR();
|
||||
|
||||
#ifdef GLSL4_API
|
||||
// FIXME maybe GL_UNSIGNED_SHORT could be better than GL_SHORT
|
||||
GSInputLayoutOGL vert_format[] =
|
||||
{
|
||||
{0 , 4 , GL_SHORT , GL_FALSE , sizeof(VertexGPU) , (const GLvoid*)(0) } , // vertex
|
||||
{0 , 2 , GL_SHORT , GL_FALSE , sizeof(VertexGPU) , (const GLvoid*)(0) } , // vertex
|
||||
{1 , 4 , GL_UNSIGNED_BYTE , GL_TRUE , sizeof(VertexGPU) , (const GLvoid*)(8) } , // color
|
||||
{2 , 4 , GL_UNSIGNED_BYTE , GL_TRUE , sizeof(VertexGPU) , (const GLvoid*)(12) } , // z value. FIXME WTF 4 unsigned byte, why not a full integer
|
||||
{3 , 3 , GL_FLOAT , GL_FALSE , sizeof(VertexGPU) , (const GLvoid*)(16) } , // tex coord
|
||||
|
@ -596,7 +594,7 @@ bool ZZCreate(int _width, int _height)
|
|||
glBindBuffer(GL_ARRAY_BUFFER, g_vboBuffers[i]);
|
||||
glBufferData(GL_ARRAY_BUFFER, 0x100*sizeof(VertexGPU), NULL, GL_STREAM_DRAW);
|
||||
#ifdef GLSL4_API
|
||||
vertex_array->set_internal_format(vert_format, 4);
|
||||
vertex_array->set_internal_format();
|
||||
#endif
|
||||
}
|
||||
vb_buffer_allocated = true; // mark the buffer allocated
|
||||
|
@ -680,7 +678,7 @@ bool ZZCreate(int _width, int _height)
|
|||
glGenBuffers(1, &vboRect);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboRect);
|
||||
#ifdef GLSL4_API
|
||||
vertex_array->set_internal_format(vert_format, 4);
|
||||
vertex_array->set_internal_format();
|
||||
#endif
|
||||
|
||||
vector<VertexGPU> verts(4);
|
||||
|
|
|
@ -137,8 +137,7 @@ struct GlobalUniform {
|
|||
float linear[2*4];
|
||||
};
|
||||
void SettleFloat(uint indice, const float* v) {
|
||||
assert(indice >= 0);
|
||||
assert(indice + 3 < sizeof(linear));
|
||||
assert(indice + 3 < 2*4);
|
||||
linear[indice+0] = v[0];
|
||||
linear[indice+1] = v[1];
|
||||
linear[indice+2] = v[2];
|
||||
|
@ -163,8 +162,7 @@ struct ConstantUniform {
|
|||
float linear[8*4];
|
||||
};
|
||||
void SettleFloat(uint indice, const float* v) {
|
||||
assert(indice >= 0);
|
||||
assert(indice + 3 < sizeof(linear));
|
||||
assert(indice + 3 < 8*4);
|
||||
linear[indice+0] = v[0];
|
||||
linear[indice+1] = v[1];
|
||||
linear[indice+2] = v[2];
|
||||
|
@ -191,8 +189,7 @@ struct FragmentUniform {
|
|||
float linear[13*4];
|
||||
};
|
||||
void SettleFloat(uint indice, const float* v) {
|
||||
assert(indice >= 0);
|
||||
assert(indice + 3 < sizeof(linear));
|
||||
assert(indice + 3 < 13*4);
|
||||
linear[indice+0] = v[0];
|
||||
linear[indice+1] = v[1];
|
||||
linear[indice+2] = v[2];
|
||||
|
@ -209,8 +206,7 @@ struct VertexUniform {
|
|||
float linear[3*4];
|
||||
};
|
||||
void SettleFloat(uint indice, const float* v) {
|
||||
assert(indice >= 0);
|
||||
assert(indice + 3 < sizeof(linear) / 4);
|
||||
assert(indice + 3 < 3*4);
|
||||
linear[indice+0] = v[0];
|
||||
linear[indice+1] = v[1];
|
||||
linear[indice+2] = v[2];
|
||||
|
@ -340,8 +336,7 @@ struct SamplerParam {
|
|||
|
||||
SamplerParam() : unit(-1), texid(0), target(0) {}
|
||||
|
||||
void set_unit(int new_unit = 0) {
|
||||
assert(new_unit >= 0);
|
||||
void set_unit(int new_unit) {
|
||||
assert(new_unit < 10);
|
||||
unit = new_unit;
|
||||
target = g_texture_target[new_unit];
|
||||
|
@ -359,6 +354,10 @@ struct SamplerParam {
|
|||
void set_texture(GLuint new_texid) {
|
||||
texid = new_texid;
|
||||
}
|
||||
|
||||
void release_texture() {
|
||||
texid = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct FRAGMENTSHADER
|
||||
|
@ -393,7 +392,7 @@ struct FRAGMENTSHADER
|
|||
//sBitwiseANDY = 4;
|
||||
//sInterlace = 5;
|
||||
//sCLUT = 6;
|
||||
samplers[sMemory+0].set_unit(0);
|
||||
samplers[sMemory].set_unit(0);
|
||||
samplers[sMemory+1].set_unit(0); // Dual context. Use same unit
|
||||
samplers[sFinal].set_unit(1);
|
||||
samplers[sBitwiseANDX].set_unit(6);
|
||||
|
@ -437,17 +436,26 @@ struct FRAGMENTSHADER
|
|||
}
|
||||
|
||||
void enable_texture() {
|
||||
samplers[0+context].enable_texture(); // sMemory is dual context
|
||||
samplers[sMemory+context].enable_texture(); // sMemory is dual context
|
||||
for (int i = 2; i < 7; i++)
|
||||
samplers[i].enable_texture();
|
||||
}
|
||||
|
||||
void set_texture(ZZshParameter param, GLuint texid) {
|
||||
if (param == 0) // sMemory is dual context
|
||||
samplers[0+context].set_texture(texid);
|
||||
if (param == sMemory) // sMemory is dual context
|
||||
samplers[sMemory+context].set_texture(texid);
|
||||
else
|
||||
samplers[param].set_texture(texid);
|
||||
}
|
||||
|
||||
void release_prog() {
|
||||
if(program) {
|
||||
glDeleteProgram(program);
|
||||
program = 0;
|
||||
}
|
||||
for (uint i = 0; i < 7 ; i++)
|
||||
samplers[i].release_texture();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -124,8 +124,8 @@ GSVertexBufferStateOGL *vertex_array;
|
|||
COMMONSHADER g_cs;
|
||||
static GLuint s_pipeline = 0;
|
||||
|
||||
FRAGMENTSHADER ppsDebug;
|
||||
FRAGMENTSHADER ppsDebug2;
|
||||
//FRAGMENTSHADER ppsDebug;
|
||||
//FRAGMENTSHADER ppsDebug2;
|
||||
|
||||
//------------------ Code
|
||||
|
||||
|
@ -392,7 +392,7 @@ inline bool LoadShaderFromFile(ZZshProgram& program, const char* DefineString, c
|
|||
return false;
|
||||
}
|
||||
|
||||
ZZLog::Error_Log("Used shader for %s... Ok",name);
|
||||
ZZLog::Error_Log("Compile shader for %s... Ok",name);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -422,25 +422,22 @@ void ZZshSetupShader() {
|
|||
PutParametersAndRun(vs, ps);
|
||||
}
|
||||
|
||||
static void ZZshSetShader(VERTEXSHADER* vs, FRAGMENTSHADER* ps) {
|
||||
if (vs == NULL || ps == NULL) return;
|
||||
|
||||
FRAGMENTSHADER* debug = ps;
|
||||
|
||||
glUseProgramStages(s_pipeline, GL_VERTEX_SHADER_BIT, vs->program);
|
||||
glUseProgramStages(s_pipeline, GL_FRAGMENT_SHADER_BIT, ps->program);
|
||||
//PutParametersAndRun(vs, ps);
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
void ZZshSetVertexShader(ZZshShaderLink prog) {
|
||||
g_vsprog = prog;
|
||||
ZZshSetShader((VERTEXSHADER*)(g_vsprog.link), (FRAGMENTSHADER*)(g_psprog.link)) ;
|
||||
|
||||
VERTEXSHADER* vs = (VERTEXSHADER*)g_vsprog.link;
|
||||
if (!vs) return;
|
||||
|
||||
glUseProgramStages(s_pipeline, GL_VERTEX_SHADER_BIT, vs->program);
|
||||
}
|
||||
|
||||
void ZZshSetPixelShader(ZZshShaderLink prog) {
|
||||
g_psprog = prog;
|
||||
ZZshSetShader((VERTEXSHADER*)(g_vsprog.link), (FRAGMENTSHADER*)(g_psprog.link)) ;
|
||||
|
||||
FRAGMENTSHADER* ps = (FRAGMENTSHADER*)g_psprog.link;
|
||||
if (!ps) return;
|
||||
|
||||
glUseProgramStages(s_pipeline, GL_FRAGMENT_SHADER_BIT, ps->program);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -482,14 +479,13 @@ void PutParametersInProgram(VERTEXSHADER* vs, FRAGMENTSHADER* ps) {
|
|||
fragment_buffer->bind();
|
||||
fragment_buffer->upload((void*)&ps->uniform_buffer[ps->context]);
|
||||
|
||||
g_cs.enable_texture();
|
||||
|
||||
#ifdef ENABLE_MARKER
|
||||
char* debug = new char[100];
|
||||
sprintf(debug, "FS(%d): enable texture", ps->program);
|
||||
if (GLEW_GREMEDY_string_marker) glStringMarkerGREMEDY(0, debug);
|
||||
#endif
|
||||
|
||||
g_cs.enable_texture();
|
||||
ps->enable_texture();
|
||||
}
|
||||
|
||||
|
@ -547,13 +543,8 @@ static __forceinline bool LOAD_PS(char* DefineString, const char* name, FRAGMENT
|
|||
inline bool LoadEffects()
|
||||
{
|
||||
// clear the textures
|
||||
for(u32 i = 0; i < ArraySize(ppsTexture); ++i) {
|
||||
SAFE_RELEASE_PROG(ppsTexture[i].prog);
|
||||
}
|
||||
|
||||
#ifndef _DEBUG
|
||||
memset(ppsTexture, 0, sizeof(ppsTexture));
|
||||
#endif
|
||||
for(u32 i = 0; i < ArraySize(ppsTexture); ++i)
|
||||
ppsTexture[i].release_prog();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -623,8 +614,8 @@ bool ZZshLoadExtraEffects() {
|
|||
if (!LOAD_PS(DefineString, "Convert32to16PS", ppsConvert32to16, cgfProf, 0, "")) bLoadSuccess = false;
|
||||
|
||||
// DEBUG
|
||||
if (!LOAD_PS(DefineString, "ZeroDebugPS", ppsDebug, cgfProf, 0, "")) bLoadSuccess = false;
|
||||
if (!LOAD_PS(DefineString, "ZeroDebug2PS", ppsDebug2, cgfProf, 0, "")) bLoadSuccess = false;
|
||||
// if (!LOAD_PS(DefineString, "ZeroDebugPS", ppsDebug, cgfProf, 0, "")) bLoadSuccess = false;
|
||||
// if (!LOAD_PS(DefineString, "ZeroDebug2PS", ppsDebug2, cgfProf, 0, "")) bLoadSuccess = false;
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
return true;
|
||||
|
@ -656,7 +647,7 @@ static ZZshProgram LoadShaderFromType(int type, int texfilter, int texwrap, int
|
|||
if (!LoadShaderFromFile(program, DefineString, name, GL_FRAGMENT_SHADER))
|
||||
return LoadShaderFromFile(program, DefineString, name, GL_FRAGMENT_SHADER, true);
|
||||
|
||||
ZZLog::Debug_Log("Used shader for type:%d filter:%d wrap:%d for:%d depth:%d aem:%d color:%d decompression:%d ctx:%d... Ok \n", type, texfilter, texwrap, fog, writedepth, testaem, exactcolor, ps, context);
|
||||
ZZLog::Debug_Log("Create new shader for type:%d filter:%d wrap:%d for:%d depth:%d aem:%d color:%d decompression:%d ctx:%d... Ok \n", type, texfilter, texwrap, fog, writedepth, testaem, exactcolor, ps, context);
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
return program;
|
||||
|
@ -699,6 +690,7 @@ FRAGMENTSHADER* ZZshLoadShadeEffect(int type, int texfilter, int fog, int testae
|
|||
GL_REPORT_ERRORD();
|
||||
|
||||
if( glGetError() != GL_NO_ERROR ) {
|
||||
ZZLog::Check_GL_Error();
|
||||
ZZLog::Error_Log("Failed to load shader %d,%d,%d,%d.", type, fog, texfilter, 4*clamp.wms+clamp.wmt);
|
||||
if (pbFailed != NULL ) *pbFailed = true;
|
||||
return pf;
|
||||
|
|
|
@ -126,7 +126,6 @@ layout(location = 0) out vertex VSout;
|
|||
|
||||
layout(location = 0) in vertex PSin;
|
||||
|
||||
// NOTE: Basic s/gl_FragData[X]/FragDataX/ I think
|
||||
// FIXME: host only do glDrawBuffers of 1 buffers not 2. I think this is a major bug
|
||||
layout(location = 0) out vec4 FragData0;
|
||||
layout(location = 1) out vec4 FragData1;
|
||||
|
@ -603,6 +602,7 @@ half4 ps2FinalColor(half4 col)
|
|||
half4 ps2FinalColor(half4 col)
|
||||
{
|
||||
return col * g_fOneColor.xxxy + g_fOneColor.zzzw;
|
||||
//return vec4(1.0f,0.0f,1.0f, 0.8f);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -765,7 +765,7 @@ void CRTCTargInterPS() {
|
|||
void CRTCTargPS() {
|
||||
float4 c = BilinearFloat16(PSin.tex.xy);
|
||||
// FIXME DEBUG: to validate tex coord on blit
|
||||
//vec4 c = vec4(PSin.tex.x/512.0f, PSin.tex.y/512.0f, 0.0, 1.0);
|
||||
//c = vec4(PSin.tex.x/512.0f, PSin.tex.y/512.0f, 0.0, 1.0);
|
||||
c.w = g_fc0.w * c.w * g_fOneColor.x + g_fOneColor.y;
|
||||
FragData0 = c;
|
||||
}
|
||||
|
@ -821,11 +821,12 @@ void ZeroPS() {
|
|||
}
|
||||
|
||||
void ZeroDebugPS() {
|
||||
FragData0 = vec4(0.0, 1.0, 0.0, 1.0);
|
||||
FragData0 = vec4(0.0, 1.0, 0.0, 0.5);
|
||||
//FragData0 = vec4(PSin.position.x, PSin.position.y, 1.0, 0.5);
|
||||
}
|
||||
|
||||
void ZeroDebug2PS() {
|
||||
FragData0 = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
FragData0 = vec4(1.0, 0.0, 0.0, 0.5);
|
||||
}
|
||||
|
||||
void BaseTexturePS() {
|
||||
|
@ -876,30 +877,37 @@ void Convert32to16PS() {
|
|||
#ifdef VERTEX_SHADER
|
||||
|
||||
float4 OutPosition() {
|
||||
float4 Position;
|
||||
Position.xy = Vert.xy * g_fPosXY.xy + g_fPosXY.zw;
|
||||
Position.z = (log(g_fc0.y + dot(g_fZ, SecondaryColor.zyxw)) * g_fZNorm.x + g_fZNorm.y) * g_fZMin.y + dot(g_fZ, SecondaryColor.zyxw) * g_fZMin.x ;
|
||||
Position.w = g_fc0.y;
|
||||
return Position;
|
||||
float4 position;
|
||||
position.xy = vec2(Vert.xy) * g_fPosXY.xy + g_fPosXY.zw;
|
||||
position.z = (log(g_fc0.y + dot(g_fZ, SecondaryColor.zyxw)) * g_fZNorm.x + g_fZNorm.y) * g_fZMin.y + dot(g_fZ, SecondaryColor.zyxw) * g_fZMin.x ;
|
||||
position.w = g_fc0.y;
|
||||
return position;
|
||||
}
|
||||
|
||||
// just smooth shadering
|
||||
void RegularVS() {
|
||||
gl_Position = OutPosition();
|
||||
float4 position = OutPosition();
|
||||
gl_Position = position;
|
||||
|
||||
VSout.color = Color;
|
||||
|
||||
DOZWRITE(VSout.z = SecondaryColor * g_fZBias.x + g_fZBias.y;)
|
||||
DOZWRITE(VSout.z.w = g_fc0.y;)
|
||||
}
|
||||
|
||||
// diffuse texture mapping
|
||||
void TextureVS() {
|
||||
gl_Position = OutPosition();
|
||||
float4 position = OutPosition();
|
||||
gl_Position = position;
|
||||
|
||||
VSout.color = Color;
|
||||
|
||||
#ifdef PERSPECTIVE_CORRECT_TEX
|
||||
VSout.tex.xyz = TexCoord.xyz;
|
||||
#else
|
||||
VSout.tex.xy = TexCoord.xy/TexCoord.z;
|
||||
#endif
|
||||
|
||||
DOZWRITE(VSout.z = SecondaryColor * g_fZBias.x + g_fZBias.y;)
|
||||
DOZWRITE(VSout.z.w = g_fc0.y;)
|
||||
}
|
||||
|
@ -907,8 +915,11 @@ void TextureVS() {
|
|||
void RegularFogVS() {
|
||||
float4 position = OutPosition();
|
||||
gl_Position = position;
|
||||
|
||||
VSout.color = Color;
|
||||
|
||||
VSout.fog = position.z * g_fBilinear.w;
|
||||
|
||||
DOZWRITE(VSout.z = SecondaryColor * g_fZBias.x + g_fZBias.y;)
|
||||
DOZWRITE(VSout.z.w = g_fc0.y;)
|
||||
}
|
||||
|
@ -916,20 +927,24 @@ void RegularFogVS() {
|
|||
void TextureFogVS() {
|
||||
float4 position = OutPosition();
|
||||
gl_Position = position;
|
||||
|
||||
VSout.color = Color;
|
||||
|
||||
#ifdef PERSPECTIVE_CORRECT_TEX
|
||||
VSout.tex.xyz = TexCoord.xyz;
|
||||
#else
|
||||
VSout.tex.xy = TexCoord.xy/TexCoord.z;
|
||||
#endif
|
||||
|
||||
VSout.fog = position.z * g_fBilinear.w;
|
||||
|
||||
DOZWRITE(VSout.z = SecondaryColor * g_fZBias.x + g_fZBias.y;)
|
||||
DOZWRITE(VSout.z.w = g_fc0.y;)
|
||||
}
|
||||
|
||||
void BitBltVS() {
|
||||
vec4 position;
|
||||
position.xy = Vert.xy * g_fBitBltPos.xy + g_fBitBltPos.zw;
|
||||
position.xy = vec2(Vert.xy) * g_fBitBltPos.xy + g_fBitBltPos.zw;
|
||||
position.zw = g_fc0.xy;
|
||||
gl_Position = position;
|
||||
|
||||
|
|
Loading…
Reference in New Issue