OpenGL纹理呈现出奇怪的中断

时间:2015-09-24 16:48:25

标签: opengl textures

我正在研究一个OpenGL引擎,我的纹理很奇怪。纹理大多是完整和有效的,但它们几乎没有奇怪的中断。这就是它的样子。

Image

右下角是纹理应该是什么样子,那里还有随机着色的蓝色正方形。这些实心方块(没有纹理)没有这些中断。

我可以提供代码,但我不确定要展示什么,因为我已经到处检查过,而且我不知道问题出在哪里。

我正在研究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;
    }

}

1 个答案:

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

编辑:

显然我的代数不在它应该的位置,我说你能做什么(现在有罢工)是完全错误的,抱歉