В настоящее время я работаю над средством рендеринга 2D-плиток. Я обнаружил, что переключение VAO слишком снижает производительность. Поэтому я решил упаковать плитку партиями. Мне удалось визуализировать каждую плитку в сетке определенного размера. Я решил, что буду использовать один текстурный атлас, и чтобы задать каждую текстуру, я просто изменю их текстурные координаты. Я решил, что сделаю это с помощью SSBO и что внутри шейдера я буду использовать gl_InstanceId, чтобы определить, какой набор вершин или координат текстуры использовать. На данный момент я просто применил ко всем из них одни и те же координаты текстуры, а позже изменю это.
Однако проблема в том, что текстура не применяется к каждой плитке. , отображается только один тексел, в результате чего получается один сплошной цвет.
Вот результат
Некаркасная визуализация
Вот это каркасный вариант
каркасный рендер
наконец, вот мой минимальный воспроизводимый пример; (обратите внимание, что единственный внешний код предназначен для класса текстуры. Я тестировал этот класс раньше, и он работал. Я вырезал его, потому что нашел код слишком длинным. Если вы хотите, чтобы я его добавил, дайте мне знать.)
Я знаю, что это долго, но это весь код, и мне удалось отследить проблему (может быть?)
Я думаю, что это может быть как-то связано с координатами текстуры. Хотя я не знаю, как это исправить или даже в чем проблема.
Код: Выделить всё
package test;
import gfx.Render;
import gfx.ShaderProgram;
import gfx.Texture;
import org.joml.Matrix4f;
import org.lwjgl.glfw.GLFWKeyCallback;
import org.lwjgl.opengl.GL;
import org.lwjgl.system.MemoryUtil;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL15.GL_STATIC_DRAW;
import static org.lwjgl.opengl.GL20.glEnableVertexAttribArray;
import static org.lwjgl.opengl.GL20.glVertexAttribPointer;
import static org.lwjgl.opengl.GL30.*;
import static org.lwjgl.opengl.GL31.glDrawElementsInstanced;
import static org.lwjgl.opengl.GL43.GL_SHADER_STORAGE_BUFFER;
import static org.lwjgl.system.MemoryUtil.memFree;
public class MinimalReproducibleExample {
private int mapWidth = 50, mapHeight = 50;
private float tileSize = 0.1f;
private int vaoId;
private int iboId;
public float camX = 0.0f, camY = 0.0f;
public float scale = 1.0f;
private int usboId;
Texture tt;
ShaderProgram shaderProgram;
private float[] vertices;
private final int[] indices = new int[]{
0, 1, 3, 3, 1, 2,
};
private FloatBuffer offsetBuffer;
private FloatBuffer tpBuffer;
long windowId;
private Matrix4f projectionMatrix;
static float safeZoneX, safeZoneY;
private void setupOrthographicProjection() {
float orthoHeight = 10.0f; // Adjust this based on your scene's needs
float orthoWidth = orthoHeight * 1080/920;
safeZoneX = orthoWidth;
safeZoneY = orthoHeight;
projectionMatrix = new Matrix4f().setOrtho2D(-orthoWidth / 2, orthoWidth / 2, -orthoHeight / 2, orthoHeight / 2);
}
public MinimalReproducibleExample() {
if(!glfwInit())
System.exit(1);
windowId = glfwCreateWindow(1080, 920, "TEST WINDOW", 0, 0);
if(windowId == 0)
System.exit(1);
glfwMakeContextCurrent(windowId);
glfwShowWindow(windowId);
GL.createCapabilities();
setupOrthographicProjection();
ShaderProgram.loadShaderPrograms();
tt = Texture.loadTexture("texture_atlases/atlas-1.png");
float[] offsets = new float[mapWidth * mapHeight * 2];
float[] texPos = new float[mapWidth * mapHeight * 8];
vertices = new float[]{
-tileSize, tileSize, 0.0f,
-tileSize, -tileSize, 0.0f,
tileSize, -tileSize, 0.0f,
tileSize, tileSize, 0.0f,
};
float[] test = new float[]{
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f
};
int index = 0;
for (int x = 0; x < mapWidth; x++) {
for (int y = 0; y < mapHeight; y++) {
float xPos = (float) x * tileSize;
float yPos = (float) y * tileSize;
offsets[index++] = xPos;
offsets[index++] = yPos;
}
}
index = 0;
for(int i = 0; i < mapWidth * mapHeight * 8; i++) {
texPos[i] = test[index];
index++;
if(index >= 8) {
index = 0;
}
}
offsetBuffer = MemoryUtil.memAllocFloat(offsets.length);
offsetBuffer.put(offsets).flip();
tpBuffer = MemoryUtil.memAllocFloat(texPos.length);
tpBuffer.put(texPos).flip();
shaderProgram = ShaderProgram.getShaderProgram("test_program");
ShaderProgram.useProgram("test_program");
vaoId = glGenVertexArrays();
glBindVertexArray(vaoId);
// Store vertex data off-heap
FloatBuffer vertexData = MemoryUtil.memAllocFloat(vertices.length);
vertexData.put(vertices).flip();
// Create and bind VBO for vertices
int vboId = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, vertexData, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(0);
memFree(vertexData);
// Store index data off-heap
IntBuffer indexData = MemoryUtil.memAllocInt(indices.length);
indexData.put(indices).flip();
// Create and bind IBO for indices
iboId = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboId);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexData, GL_STATIC_DRAW);
memFree(indexData);
// Create and bind the SSBO for offsets
int ssboId = glGenBuffers();
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboId);
glBufferData(GL_SHADER_STORAGE_BUFFER, offsetBuffer, GL_STATIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssboId);
// Create and bind the SSBO for texture coordinates
usboId = glGenBuffers();
glBindBuffer(GL_SHADER_STORAGE_BUFFER, usboId);
glBufferData(GL_SHADER_STORAGE_BUFFER, tpBuffer, GL_STATIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, usboId);
// Unbind VAO
glBindVertexArray(0);
glfwSetKeyCallback(windowId, new GLFWKeyCallback() {
@Override
public void invoke(long l, int i, int i1, int i2, int i3) {
if(i == GLFW_KEY_F1) {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDisable(GL_TEXTURE_2D);
}
if(i == GLFW_KEY_F2) {
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_TEXTURE_2D);
}
}
});
while(!glfwWindowShouldClose(windowId)) {
glfwPollEvents();
//handle camera movement;
if(glfwGetKey(windowId, GLFW_KEY_D) == GLFW_TRUE) {
camX -= 0.01f;
}
if(glfwGetKey(windowId, GLFW_KEY_A) == GLFW_TRUE) {
camX += 0.01f;
}
if(glfwGetKey(windowId, GLFW_KEY_W) == GLFW_TRUE) {
camY -= 0.01f;
}
if(glfwGetKey(windowId, GLFW_KEY_S) == GLFW_TRUE) {
camY += 0.01f;
}
if(glfwGetKey(windowId, GLFW_KEY_E) == GLFW_TRUE) {
scale += 0.001f;
}
if(glfwGetKey(windowId, GLFW_KEY_Q) == GLFW_TRUE) {
scale -= 0.001f;
}
if(scale >=10.0f) {
scale = 10.0f;
}
if(scale= 8) {
index = 0;
}
}
Подробнее здесь: https://stackoverflow.com/questions/786 ... sing-ssbos