OpenGL - 无法立即将所有数据传递到着色器

时间:2015-08-14 00:34:57

标签: performance opengl go glsl shader

我正在尝试使用opengl 3.3

在四边形(2个三角形)上显示纹理

在四边形上绘制纹理效果很好;然而,当我有一个纹理(精灵地图集),但使用2个四边形(对象)来显示地图集的不同部分。在绘制循环中,它们最终会在各自的翻译位置切换回第四个(一个消失而不是再次出现等)。

我绘制这个的方式并不是每个四边形(或对象)的标准DrawElements,但是我将所有四边形,uv,平移等包装起来作为一个大块(作为“in”变量)发送到着色器:顶点着色器:

 #version 330 core

// Input vertex data, different for all executions of this shader.
in vec3 vertexPosition_modelspace;
in vec3 vertexColor;
in vec2 vertexUV;
in vec3 translation;
in vec4 rotation;
in vec3 scale;
// Output data ; will be interpolated for each fragment.
out vec2 UV;
// Output data ; will be interpolated for each fragment.
out vec3 fragmentColor;
// Values that stay constant for the whole mesh.
uniform mat4 MVP;

...

void main(){


    mat4 Model = mat4(1.0);

    mat4 t = translationMatrix(translation);
    mat4 s = scaleMatrix(scale);
    mat4 r = rotationMatrix(vec3(rotation), rotation[3]);

    Model *= t * r * s;


    gl_Position = MVP * Model * vec4 (vertexPosition_modelspace,1); //* MVP;

    // The color of each vertex will be interpolated
    // to produce the color of each fragment
    fragmentColor = vertexColor;

    // UV of the vertex. No special space for this one.
    UV = vertexUV;

}

顶点着色器是否正常工作,我认为它会带有大量数据 - 它会将每个段单独传递为单独均匀,因为它看起来不像?我的思路是否正确?

为了完整性,这是我的片段着色器:

#version 330 core

// Interpolated values from the vertex shaders
in vec3 fragmentColor;

// Interpolated values from the vertex shaders
in vec2 UV;

// Ouput data
out vec4 color;

// Values that stay constant for the whole mesh.
uniform sampler2D myTextureSampler;

void main()
{

    // Output color = color of the texture at the specified UV
    color = texture2D( myTextureSampler, UV ).rgba;

}

我已经提出了更多信息的请求,因此我将把这些数据绑定到顶点着色器。以下代码只是我用于翻译的代码。我有更多的颜色,旋转,比例,紫外线等:

gl.BindBuffer(gl.ARRAY_BUFFER, tvbo)
gl.BufferData(gl.ARRAY_BUFFER, len(data.Translations)*4, gl.Ptr(data.Translations), gl.DYNAMIC_DRAW)
tAttrib := uint32(gl.GetAttribLocation(program, gl.Str("translation\x00")))
gl.EnableVertexAttribArray(tAttrib)
gl.VertexAttribPointer(tAttrib, 3, gl.FLOAT, false, 0, nil)

...

gl.DrawElements(gl.TRIANGLES, int32(len(elements)), gl.UNSIGNED_INT, nil)

2 个答案:

答案 0 :(得分:0)

您只有一个sampler2D

  • 这意味着您可以随意使用单一纹理
  • 无论你绑定了多少人。
  • 如果您确实需要将数据作为单个块传递
  • 然后你应该为每个纹理添加采样器
  • 不确定您有多少个物体/纹理
  • 但是你受到这种数据传递方式的纹理单位的gfx hw限制
  • 您还需要在数据中添加另一个值,告诉哪个基元使用哪个纹理单元
  • 和内部片段然后选择正确的纹理采样器......

你应该添加这样的东西:

// vertex
in int usedtexture;
out int txr;

void main()
 {
 txr=usedtexture;
 }

// fragment
uniform sampler2D myTextureSampler0;
uniform sampler2D myTextureSampler1;
uniform sampler2D myTextureSampler2;
uniform sampler2D myTextureSampler3;
in vec2 UV;
in int txr;
out vec4 color;
void main
 {
      if (txr==0) color = texture2D( myTextureSampler0, UV ).rgba;
 else if (txr==1) color = texture2D( myTextureSampler1, UV ).rgba;
 else if (txr==2) color = texture2D( myTextureSampler2, UV ).rgba;
 else if (txr==3) color = texture2D( myTextureSampler3, UV ).rgba;
 else color=vec4(0.0,0.0,0.0,0.0);
 }

由于以下原因,这种传球方式并不好:

  • 使用的纹理数限制为HW纹理单位限制
  • 如果你的渲染需要额外的纹理,如普通/光泽/光照贴图
  • 然后每个对象类型需要超过1个纹理,并且您的限制突然被2,3,4 ...
  • 除以
  • 你需要在片段内部使用if/switch语句,这可能会使事情变得相当缓慢
  • 是的,你可以少吃早午餐,但是你需要随时访问所有纹理,增加gfx的热应力......

这种传递适用于

  • 单个图像中的所有纹理(如您提到的纹理图集)
  • 这种方式可以更快,对于具有少量对象类型(或材料)但具有大对象数的场景来说是合理的......

答案 1 :(得分:0)

由于我需要更多关于此事的意见,我将此页面链接到reddit,有人能够帮助我做出一个回复!无论如何,reddit链接在这里:

https://www.reddit.com/r/opengl/comments/3gyvlt/opengl_passing_all_scene_data_into_shader_each/

将所有顶点作为一个数据结构传递到顶点着色器后看到两个单独的纹理/四边形的问题是因为我的元素索引关闭了。我需要为我的2个三角形(四边形)对象确定每组顶点的正确索引。只需要做这样的事情:

        vertexInfo.Elements = append(vertexInfo.Elements, uint32(idx*4), uint32(idx*4+1), uint32(idx*4+2), uint32(idx*4), uint32(idx*4+2), uint32(idx*4+3))