OpenGL-一次将所有数据传递到着色器时遇到麻烦

I'm trying to display textures on quads (2 triangles) using opengl 3.3

Drawing a texture on a quad works great; however when I have ONE textures (sprite atlas) but using 2 quads(objects) to display different parts of the atlas. When in draw loop, they end up switching back and fourth(one disappears than appears again, etc) at their individual translated locations.

The way I'm drawing this is not the standard DrawElements for each quad(or object) but I package all quads, uv, translations, etc send them up to the shader as one big chunk (as "in" variables): Vertex shader:

 #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;

}

Is the vertex shader working as I think it would with a large chunk of data - that it draws each segment passed up as uniform individually because it does not seem like it? Is my train of thought correct on this?

For completeness this is my fragment shader:

#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;

}

A request for more information was made so I will put how i bind this data up to the vertex shader. The following code is just one I use for my translations. I have more for color, rotation, scale, uv, etc:

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)
dtntjwkl83750
dtntjwkl83750 抱歉,我有输入错误,我将它们作为“输入”变量传递给顶点着色器。对于整个场景,每次绘制时,将场景中的所有顶点,平移,缩放,旋转,uv,颜色等打包到不同的“输入”变量中。这样做是因为绘制大量对象的性能更好(每个对象都没有绘制调用)。
大约 5 年之前 回复
doutizhou5312
doutizhou5312 您可以通过glDrawElements/Arrays调用发布渲染方法吗?如Spektre所述,您只能在进行渲染调用之前设置一次统一变量,然后再设置一次并再次渲染。
大约 5 年之前 回复
douyalin0847
douyalin0847 您是什么意思,您将数据作为(作为统一变量)传递给您,您只能在渲染整个对象之前更改统一,因此您不能在着色器外部切换纹理(因为您一次绘制所有内容)...
大约 5 年之前 回复
doutang2017
doutang2017 深度测试已关闭...而且这些对象也不位于彼此之上。
大约 5 年之前 回复
doucuo8618
doucuo8618 绘制相同的纹理,但是如果每个坐标都不同,则我有uv坐标。这是一个精灵地图集
大约 5 年之前 回复
doudiaozhi6658
doudiaozhi6658 我认为您不能在一个绘制调用中绘制两个具有不同纹理的四边形,除非您的片段着色器有某种方式知道要应用于哪个四边形的纹理。
大约 5 年之前 回复
doumao8803
doumao8803 “他们最终在他们各自的翻译位置切换回去,第四个(一个消失,然后再出现,等等)。”听起来像Z战。四边形的坐标是什么?确保它们与相机的距离不完全相同(或禁用深度测试)。
大约 5 年之前 回复

2个回答



由于我需要对此事进行更多输入,因此我将此页面链接到了reddit,有人可以帮助我做出回应! 无论如何,reddit链接都在这里:</ p>

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

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

  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))
</ code> </ pre>
</ div>

展开原文

原文

Since I needed more input on this matter, I linked this page to reddit and someone was able to help me with one response! Anyways the reddit link is here:

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

The issue of seeing two individual textures/quads after passing all vertices as one data structure over to vertex shader was because my element indices were off. I needed to determine the correct index of each set of vertices for my 2 triangle(quad) objects. Simply had to do something like this:

        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))



您只有一个 sampler2D </ code> </ strong> </ p>

< ul>

这意味着您只有一个纹理可供使用</ li>
,无论您绑定了多少纹理。</ li>
如果您真的需要通过 数据作为单个块</ li>
然后您应该为每个获得的纹理添加采样器</ li>
不确定要拥有多少个对象/纹理</ li>
但是您会受到这种数据传递方式对纹理单元的gfx hw限制</ li>
,还需要向数据中添加另一个值,以告诉哪个原始对象使用哪个纹理单元</ li>
在片段内部,然后选择正确的纹理采样器... </ li>
</ ul>

您应该添加以下内容:</ p>

   //顶点
in int usedtexture;
out int txr;

void main()
{
txr = usedtexture;
}

// fragment
uniform sampler2D myTextureSampler0;
uniform sampler2D myTextureSampler1;
uniform sampler2D myTextureSampler2;
uniform sampler2D myTextureSample r3;
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;
否则(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);
}
</ code> </ pre>

这种传递方式是 由于以下原因,效果不好:</ strong> </ p>


  • 已使用的纹理数量限制为硬件纹理单位限制</ li>
  • 需要其他纹理,例如法线/光泽/光照贴图</ li>
  • ,那么每种对象类型需要1个以上的纹理,并且您的限制突然除以2,3,4 ... </ li>
  • 您需要在片段内添加 if / switch </ code>语句,这可能会大大降低速度</ li>
  • 是的,您可以减少它的早午餐,但随后您将需要访问所有纹理 在gfx上无缘无故地增加热应力的时间... </ li >
    </ ul>

    这种传递方式适用于</ strong> </ p>


    • 单个图像内的所有纹理( 正如您提到的纹理图集)</ li>
    • ,这种方法可以更快地实现,并且对于对象类型(或材质)数量少但对象数量大的场景来说是合理的……</ li>
      </ ul>
      </ div>

展开原文

原文

You have just single sampler2D

  • which means you have just single texture at your disposal
  • regardless on how many of them you bind.
  • If you really need to pass the data as single block
  • then you should add sampler per each texture you got
  • not sure how many objects/textures you have
  • but you are limited by gfx hw limit on texture units with this way of data passing
  • also you need to add another value to your data telling which primitive use which texture unit
  • and inside fragment then select the right texture sampler ...

You should add stuff like this:

// 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);
 }

This way of passing is not good for these reasons:

  • number of used textures is limited to HW texture units limit
  • if your rendering would need additional textures like normal/shininess/light maps
  • then you need more then 1 texture per object type and your limit is suddenly divided by 2,3,4...
  • You need if/switch statements inside fragment which can slow things down considerably
  • Yes you can do it brunch less but then you would need to access all textures all the time increasing heat stress on gfx without reason...

This kind of passing is suitable for

  • all textures inside single image (as you mentioned texture atlas)
  • which can be faster this way and reasonable for scenes with small number of object types (or materials) but large object count...

dongmi5020
dongmi5020 顶点着色器不完整,因为要键入的内容很多...我有辅助方法可以处理顶点着色器中T-R-S的矩阵。 我试图通过放置“ ...”来表示代码部分丢失,以减轻混乱
大约 5 年之前 回复
drkbpwk609294
drkbpwk609294 在这种情况下,可以...当我尝试编译您的着色器时,您在顶点着色器中遇到错误:0(24):错误C1008:未定义变量“ translationMatrix” 0(25):错误C1008:未定义变量“ scaleMatrix” 0( 26):错误C1008:未定义的变量“ rotationMatrix”也应作为制服传递。 因此它不会链接,而您将使用固定功能进行渲染(除非您没有发布整个着色器...)
大约 5 年之前 回复
duanjiao5543
duanjiao5543 抱歉,我编辑了我的帖子,以解释我在做什么。 因此,我要传递一个巨大的纹理地图集,并将该地图集分解为每个图片中不同的uv坐标。
大约 5 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐