为了账号安全,请及时绑定邮箱和手机立即绑定

OpenGL - 无法一次将所有数据传递到着色器中

OpenGL - 无法一次将所有数据传递到着色器中

HUWWW 2021-11-01 15:08:18
我正在尝试使用 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 shadersin vec3 fragmentColor;// Interpolated values from the vertex shadersin vec2 UV;// Ouput dataout 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;}
查看完整描述

2 回答

?
叮当猫咪

TA贡献1776条经验 获得超12个赞

你只有单身 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);

 }

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

  • 使用的纹理数量仅限于硬件纹理单元限制

  • 如果您的渲染需要额外的纹理,如法线/光泽度/光照贴图

  • 那么每个对象类型需要超过 1 个纹理,并且您的限制突然除以 2,3,4 ...

  • 您需要if/switch片段内的语句,这会大大减慢速度

  • 是的,您可以少吃早午餐,但是您需要一直访问所有纹理,从而无缘无故地增加 gfx 的热应力...

这种传球适合

  • 单个图像中的所有纹理(正如你提到的纹理图集)

  • 对于具有少量对象类型(或材料)但对象数量较多的场景,这种方式可以更快并且合理......


查看完整回答
反对 回复 2021-11-01
  • 2 回答
  • 0 关注
  • 143 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号