我正在研究一个OpenGL引擎,我的纹理很奇怪。纹理大多是完整和有效的,但它们几乎没有奇怪的中断。这就是它的样子。
右下角是纹理应该是什么样子,那里还有随机着色的蓝色正方形。这些实心方块(没有纹理)没有这些中断。
我可以提供代码,但我不确定要展示什么,因为我已经到处检查过,而且我不知道问题出在哪里。
我正在研究Java和C ++版本。这是Java中的渲染器(如果你想看到其他东西只是问):
public class BatchRenderer2D extends Renderer2D {
private static final int MAX_SPRITES = 60000;
private static final int VERTEX_SIZE = Float.BYTES * 3 + + Float.BYTES * 2 + Float.BYTES * 1 + Float.BYTES * 1;
private static final int SPRITE_SIZE = VERTEX_SIZE * 4;
private static final int BUFFER_SIZE = SPRITE_SIZE * MAX_SPRITES;
private static final int INDICES_SIZE = MAX_SPRITES * 6;
private static final int SHADER_VERTEX_INDEX = 0;
private static final int SHADER_UV_INDEX = 1;
private static final int SHADER_TID_INDEX = 2;
private static final int SHADER_COLOR_INDEX = 3;
private int VAO;
private int VBO;
private IndexBuffer IBO;
private int indexCount;
private FloatBuffer buffer;
private List<Integer> textureSlots = new ArrayList<Integer>();
public BatchRenderer2D() {
init();
}
public void destroy() {
IBO.delete();
glDeleteBuffers(VBO);
glDeleteVertexArrays(VAO);
glDeleteBuffers(VBO);
}
public void init() {
VAO = glGenVertexArrays();
VBO = glGenBuffers();
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, BUFFER_SIZE, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(SHADER_VERTEX_INDEX);
glEnableVertexAttribArray(SHADER_UV_INDEX);
glEnableVertexAttribArray(SHADER_TID_INDEX);
glEnableVertexAttribArray(SHADER_COLOR_INDEX);
glVertexAttribPointer(SHADER_VERTEX_INDEX, 3, GL_FLOAT, false, VERTEX_SIZE, 0);
glVertexAttribPointer(SHADER_UV_INDEX, 2, GL_FLOAT, false, VERTEX_SIZE, 3 * 4);
glVertexAttribPointer(SHADER_TID_INDEX, 1, GL_FLOAT, false, VERTEX_SIZE, 3 * 4 + 2 * 4);
glVertexAttribPointer(SHADER_COLOR_INDEX, 4, GL_UNSIGNED_BYTE, true, VERTEX_SIZE, 3 * 4 + 2 * 4 + 1 * 4);
glBindBuffer(GL_ARRAY_BUFFER, 0);
int[] indices = new int[INDICES_SIZE];
int offset = 0;
for (int i = 0; i < INDICES_SIZE; i += 6) {
indices[ i ] = offset + 0;
indices[i + 1] = offset + 1;
indices[i + 2] = offset + 2;
indices[i + 3] = offset + 2;
indices[i + 4] = offset + 3;
indices[i + 5] = offset + 0;
offset += 4;
}
IBO = new IndexBuffer(indices, INDICES_SIZE);
glBindVertexArray(0);
}
@Override
public void begin() {
glBindBuffer(GL_ARRAY_BUFFER, VBO);
buffer = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY).asFloatBuffer();
}
@Override
public void submit(Renderable2D renderable) {
Vector3f position = renderable.getPosition();
Vector2f size = renderable.getSize();
Vector4f color = renderable.getColor();
List<Vector2f> uv = renderable.getUV();
float tid = renderable.getTID();
float c = 0;
float ts = 0.0f;
if (tid > 0) {
boolean found = false;
for(int i = 0; i < textureSlots.size(); i++) {
if(textureSlots.get(i) == tid) {
ts = (float)(i + 1);
found = true;
break;
}
}
if(!found) {
if(textureSlots.size() >= 32) {
end();
flush();
begin();
}
textureSlots.add((int)tid);
ts = (float)textureSlots.size();
}
} else {
int r = (int) (color.x * 255);
int g = (int) (color.y * 255);
int b = (int) (color.z * 255);
int a = (int) (color.w * 255);
c = Float.intBitsToFloat((r << 0) | (g << 8) | (b << 16) | (a << 24));
}
transformationBack.multiply(position).store(buffer);
uv.get(0).store(buffer);
buffer.put(ts);
buffer.put(c);
transformationBack.multiply(new Vector3f(position.x, position.y + size.y, position.z)).store(buffer);
uv.get(1).store(buffer);
buffer.put(ts);
buffer.put(c);
transformationBack.multiply(new Vector3f(position.x + size.x, position.y + size.y, position.z)).store(buffer);
uv.get(2).store(buffer);
buffer.put(ts);
buffer.put(c);
transformationBack.multiply(new Vector3f(position.x + size.x, position.y, position.z)).store(buffer);
uv.get(3).store(buffer);
buffer.put(ts);
buffer.put(c);
indexCount += 6;
}
@Override
public void end() {
glUnmapBuffer(GL_ARRAY_BUFFER);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
@Override
public void flush() {
for(int i = 0; i < textureSlots.size(); i++) {
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, textureSlots.get(i));
}
glBindVertexArray(VAO);
IBO.bind();
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, NULL);
IBO.unbind();
glBindVertexArray(0);
indexCount = 0;
}
}
答案 0 :(得分:1)
你没有提供,但我很确定我知道原因(有同样的问题,遵循Cherno教程?;))。就像信息一样,你的gpu是什么? (看来AMD有更多问题)。关联我的thread来源
重要部分:
Fragment Shader:
#version 330 core
if(fs_in.tid > 0.0){
int tid = int(fs_in.tid - 0.5);
texColor = texture(textures[tid], fs_in.uv);
}
根据明确说明
的GLSL 3.30规范,不允许您尝试执行此操作聚合到着色器内的数组中的采样器(使用方括号[])只能使用整数常量表达式进行索引(请参见第4.3.3节“常量表达式”)。 你的tid不是常数,所以这不起作用。
在GL 4中,这个约束有点放松(引用来自GLSL 4.50规范):
当在着色器中聚合到数组中时,采样器只能使用动态统一的整数表达式进行索引,否则结果将是未定义的。 你现在的输入也不是动态统一的,所以你也会得到不确定的结果。
(谢谢derhass)
一个“简单”的解决方案(但不是很漂亮,我相信对性能的影响很小):
switch(tid){
case 0: textureColor = texture(textures[0], fs_in.uv); break;
...
case 31: textureColor = texture(textures[31], fs_in.uv); break;
}
另外,作为一个小注释,你在广场上做了很多矩阵乘法,你可以简单地乘以第一个,然后再添加值,它提升了我的性能大约200 fps(在您的示例,乘以,然后添加y,然后添加x,然后再次减去y)
编辑:
显然我的代数不在它应该的位置,我说你能做什么(现在有罢工)是完全错误的,抱歉