Рендеринг текстур OpenGL поверх других с помощью 3D Batch RendererJAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Рендеринг текстур OpenGL поверх других с помощью 3D Batch Renderer

Сообщение Anonymous »

Итак, мой текущий рендерер OpenGL по какой-то причине рисует текстуру B с текстурой A. Я проверил слоты в RenderDoc, и они, кажется, правильно связаны с glBindTexture() и glActiveTexture(). Я не совсем понимаю, что происходит. Я заметил, что, когда камера вообще не перемещается, проблема исчезает.
Скриншот
Это основной класс:
Скриншот
Это основной класс:
р>

Код: Выделить всё

package demo;

import org.joml.Matrix4f;
import org.lwjgl.opengl.GL46;
import rebel.graphics.*;

public class Test3D {
public static void main(String[] args) {
Window window = new Window(1000, 600, "");
Renderer3D renderer3D = new Renderer3D(window.getWidth(), window.getHeight(), true);

Texture2D a = new Texture2D("project/logo.png");
Texture2D b = new Texture2D("project/texture.png");

float rotX = 0f, rotY = 0f, rotZ = 0f;

while(!window.shouldClose()){
renderer3D.clear(Color.WHITE);

renderer3D.setOrigin(0, 0);
renderer3D.drawTexture(0.5f / -2f, 0.5f / -2f, 0.5f, 0.5f, a, Color.RED);
renderer3D.drawTexture((0.5f / -2f) + 0.5f, 0.5f / -2f, 1f, 1f, b, Color.BLUE);
renderer3D.resetTransform();

renderer3D.getCamera().getViewMatrix().rotate((float) Math.toRadians(rotX), 1, 0, 0);
renderer3D.getCamera().getViewMatrix().rotate((float) Math.toRadians(rotY), 0, 1, 0);
renderer3D.getCamera().getViewMatrix().translate(0, 0, 1f);

rotX = 360 * -(window.getMouseY() / window.getHeight());
rotY = 360 * (window.getMouseX() / window.getWidth());

renderer3D.updateCamera2D();
renderer3D.render();
renderer3D.getCamera().getViewMatrix().set(new Matrix4f().identity());

System.out.println(GL46.glGetError());

window.update();
}

window.close();

}
}

И Renderer3D:

Код: Выделить всё

package rebel.graphics;

import org.joml.*;
import org.lwjgl.BufferUtils;
import rebel.FileReader;

import java.lang.Math;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.List;

import static org.lwjgl.opengl.GL46.*;

public class Renderer3D {
private int width;
private int height;
private Matrix4f proj;
private Camera camera;
private Matrix4f translation;
private VertexBuffer vertexBuffer;
private float[] vertexData;
private int maxTextureSlots;
private ShaderProgram defaultShaderProgram, currentShaderProgram;
private ArrayList  renderCallNames = new ArrayList(50);
private boolean debug = false;
private FastTextureLookup textureLookup;

private static final float FOV = (float) Math.toRadians(60.0f);

private static final float Z_NEAR = 0.01f;

private static final float Z_FAR = 1000.f;

public Renderer3D(int width, int height, boolean msaa) {
this.width = width;
this.height = height;

glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_NOTEQUAL);

float aspectRatio = (float) getWidth() / getHeight();
proj = new Matrix4f().perspective(FOV, aspectRatio,
Z_NEAR, Z_FAR);
camera = new Camera();
translation = new Matrix4f().identity();

IntBuffer d = BufferUtils.createIntBuffer(1);
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, d);
maxTextureSlots  = d.get();
textureLookup = new FastTextureLookup(maxTextureSlots);

defaultShaderProgram = new ShaderProgram(
FileReader.readFile(Renderer2D.class.getClassLoader().getResourceAsStream("3DBatchVertexShader.glsl")),
FileReader.readFile(Renderer2D.class.getClassLoader().getResourceAsStream("3DBatchFragmentShader.glsl"))
);

defaultShaderProgram.prepare();
currentShaderProgram = defaultShaderProgram;
currentShaderProgram.bind();

updateCamera2D();

VertexArray vertexArray = new VertexArray();
vertexArray.bind();

vertexArray.setVertexAttributes(
new VertexAttribute(0, 3, false, "v_pos"),
new VertexAttribute(1, 2, false, "v_uv"),
new VertexAttribute(2, 1, false, "v_texindex"),
new VertexAttribute(3, 4, false, "v_color"),
new VertexAttribute(4, 1, false, "v_thickness")
);

vertexBuffer = new VertexBuffer(1000, vertexArray.getStride());
vertexArray.build();

vertexData = new float[vertexBuffer.getNumOfVertices() * vertexBuffer.getVertexDataSize()];
}

/***
* Sets the current shader.  This shader must be compiled before calling this method!
* @param shaderProgram
*/
public void setShader(ShaderProgram shaderProgram){

if(currentShaderProgram != shaderProgram) {
currentShaderProgram = shaderProgram;
currentShaderProgram.bind();
updateCamera2D();
}
}

public void updateCamera2D(){
currentShaderProgram.setMatrix4f("v_model", getTranslation());
currentShaderProgram.setMatrix4f("v_view", getView());
currentShaderProgram.setMatrix4f("v_projection", getProj());
currentShaderProgram.setIntArray("u_textures", createTextureSlots());
}

private int[] createTextureSlots() {
int[] slots = new int[maxTextureSlots];
for (int i = 0; i < maxTextureSlots; i++) {
slots[i] = i;
}
return slots;
}
public VertexBuffer getVertexBuffer() {
return vertexBuffer;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public Matrix4f getProj() {
return proj;
}
public Camera getCamera() {
return camera;
}
public Matrix4f getView() {
return camera.getViewMatrix();
}
public Matrix4f getTranslation() {
return translation;
}
private int quadIndex;
private int nextTextureSlot;
private Matrix4f transform = new Matrix4f().identity();
private float originX, originY;
public Matrix4f getTransform() {
return transform;
}
public void setTransform(Matrix4f transform) {
this.transform = transform;
}
public void resetTransform(){
setTransform(new Matrix4f().identity());
}
public void drawTexture(float x, float y, float w, float h, Texture2D texture){
drawTexture(x, y, w, h, texture, Color.WHITE);
}
public void setOrigin(float x, float y){
this.originX = x;
this.originY = y;
}

public void drawTexture(float x, float y, float w, float h, Texture2D texture, Color color){
drawTexture(x, y, w, h, texture, color, new Rect2D(0, 0, 1, 1), false, false);
}
public void drawTexture(float x, float y, float w, float h, Texture2D texture, Color color, Rect2D rect2D, boolean xFlip, boolean yFlip) {

int slot = nextTextureSlot;
boolean isUniqueTexture = false;

//Existing texture
if (textureLookup.hasTexture(texture)) {
slot = textureLookup.getTexture(texture);
}

//Unique Texture
else {
glActiveTexture(GL_TEXTURE0 + slot);
texture.bind();
texture.setSlot(slot);
textureLookup.registerTexture(texture, slot);
isUniqueTexture = true;
}

drawQuadGL(x, y, w, h, slot, color, originX, originY, rect2D, -1, xFlip, yFlip);

if(isUniqueTexture) nextTextureSlot++;

if(nextTextureSlot == maxTextureSlots)
render("Next Batch Render [No more rebel.engine.graphics.Texture slots out of "  + maxTextureSlots + "]");

}

public void drawQuadGL(float x, float y, float w, float h, int slot, Color color, float originX, float originY, Rect2D region, float thickness, boolean xFlip, boolean yFlip){
//Translate back by origin (for rotation math)
//This usually takes everything near (0, 0)

Rect2D copy = new Rect2D(region.x, region.y, region.w, region.h);

if(xFlip){
float temp = copy.x;
copy.x = copy.w;
copy.w = temp;
}

if(yFlip){
float temp = copy.y;
copy.y = copy.h;
copy.h = temp;
}

float z = -0.25f;

Vector4f topLeft = new Vector4f(x - originX, y - originY, z, 1);
Vector4f topRight = new Vector4f(x + w - originX, y - originY, z, 1);
Vector4f bottomLeft = new Vector4f(x - originX, y + h - originY, z, 1);
Vector4f bottomRight = new Vector4f(x + w - originX, y + h - originY, z,  1);

topLeft.mul(transform);
topRight.mul(transform);
bottomLeft.mul(transform);
bottomRight.mul(transform);

//Translate forward by origin back to the current position
topLeft.x += originX;
topRight.x += originX;
bottomLeft.x += originX;
bottomRight.x += originX;

topLeft.y += originY;
topRight.y += originY;
bottomLeft.y += originY;
bottomRight.y += originY;

{
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 0] = topLeft.x;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 1] = topLeft.y;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 2] = topLeft.z;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 3] = copy.x;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 4] = copy.y;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 5] = slot;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 6] = color.r;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 7] = color.g;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 8] = color.b;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 9] = color.a;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 10] = thickness;

vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 11] = bottomLeft.x;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 12] = bottomLeft.y;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 13] = bottomLeft.z;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 14] = copy.x;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 15] = copy.h;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 16] = slot;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 17] = color.r;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 18] = color.g;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 19] = color.b;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 20] = color.a;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 21] = thickness;

vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 22] = bottomRight.x;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 23] = bottomRight.y;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 24] = bottomRight.z;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 25] = copy.w;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 26] = copy.h;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 27] = slot;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 28] = color.r;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 29] = color.g;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 30] = color.b;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 31] = color.a;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 32] = thickness;

vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 33] = topRight.x;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 34] = topRight.y;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 35] = topRight.z;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 36] = copy.w;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 37] = copy.y;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 38] = slot;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 39] = color.r;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 40] = color.g;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 41] = color.b;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 42] = color.a;
vertexData[(quadIndex * vertexBuffer.getVertexDataSize()) + 43] = thickness;

}
quadIndex++;

if(quadIndex == vertexBuffer.maxQuads())  render("Next Batch Render");
}
public void render(){
render("Final Draw Call [rebel.engine.graphics.Renderer2D.render()]");

if(debug){
System.out.println("Renderer2D (" + this + ") - Debug");

for(String call : getRenderCalls()){
System.out.print("\t" + call + "\n");
}
System.out.println("\n");
}

renderCallNames.clear();
}

public void render(String renderName) {
renderCallNames.add(renderName);

glBindBuffer(GL_ARRAY_BUFFER, getVertexBuffer().myVbo);

glBufferSubData(GL_ARRAY_BUFFER, 0, vertexData);

int numOfIndices = quadIndex * 6;
int[] indices = new int[numOfIndices];
int offset = 0;

for (int j = 0; j < numOfIndices; j += 6) {

indices[j] =         offset;
indices[j + 1] = 1 + offset;
indices[j + 2] = 2 + offset;
indices[j + 3] = 2 + offset;
indices[j + 4] = 3 + offset;
indices[j + 5] =     offset;

offset += 4;
}

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, getVertexBuffer().myEbo);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indices);
glDrawElements(GL_TRIANGLES, indices.length, GL_UNSIGNED_INT, 0);

vertexData = new float[vertexBuffer.getNumOfVertices() * vertexBuffer.getVertexDataSize()];
quadIndex = 0;
nextTextureSlot = 0;
textureLookup.clear();

}
public List getRenderCalls(){
return new ArrayList(renderCallNames);
}

public void clear(Color color) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(color.r, color.g, color.b, color.a);
}

}

Это мой вершинный шейдер:

Код: Выделить всё

#version 330 core
layout (location = 0) in vec3 v_pos;
layout (location = 1) in vec2 v_uv;
layout (location = 2) in float v_texindex;
layout (location = 3) in vec4 v_color;
layout (location = 4) in float v_thickness;

out vec2 f_uv;
out float f_texindex;
out vec4 f_color;
out vec2 f_origin;
out vec2 f_size;
out float f_thickness;

uniform mat4 v_model;
uniform mat4 v_view;
uniform mat4 v_projection;

void main() {

f_texindex = v_texindex;
f_uv = v_uv;
f_color = v_color;
f_thickness = v_thickness;

gl_Position = v_projection * v_view * v_model * vec4(v_pos, 1.0);
}
И мой фрагментный шейдер

Код: Выделить всё

#version 330 core
out vec4 FragColor;

in vec2 f_uv;

uniform sampler2D u_textures[32];
in float f_texindex;
in vec4 f_color;
in float f_thickness;
layout(origin_upper_left) in vec4 gl_FragCoord;

void main()
{

int index = int(f_texindex);

if(index == -1){
FragColor = f_color;
}
else if(index == -2){
vec2 uv = f_uv * 2.0 - 1.0;

float distance = length(uv);

if(distance = (1.0 - f_thickness))
FragColor = f_color;
else
discard;

}
else {

if(index == 0) FragColor += texture(u_textures[0], f_uv) * f_color;
if(index == 1) FragColor += texture(u_textures[1], f_uv) * f_color;
if(index == 2) FragColor += texture(u_textures[2], f_uv) * f_color;
if(index == 3) FragColor += texture(u_textures[3], f_uv) * f_color;
if(index == 4) FragColor += texture(u_textures[4], f_uv) * f_color;
if(index == 5) FragColor += texture(u_textures[5], f_uv) * f_color;
if(index == 6) FragColor += texture(u_textures[6], f_uv) * f_color;
if(index == 7) FragColor += texture(u_textures[7], f_uv) * f_color;
if(index == 8) FragColor += texture(u_textures[8], f_uv) * f_color;
if(index == 9) FragColor += texture(u_textures[9], f_uv) * f_color;
if(index == 10) FragColor += texture(u_textures[10], f_uv) * f_color;
if(index == 11) FragColor += texture(u_textures[11], f_uv) * f_color;
if(index == 12) FragColor += texture(u_textures[12], f_uv) * f_color;
if(index == 13) FragColor += texture(u_textures[13], f_uv) * f_color;
if(index == 14) FragColor += texture(u_textures[14], f_uv) * f_color;
if(index == 15) FragColor += texture(u_textures[15], f_uv) * f_color;
if(index == 16) FragColor += texture(u_textures[16], f_uv) * f_color;
if(index == 17) FragColor += texture(u_textures[17], f_uv) * f_color;
if(index == 18) FragColor += texture(u_textures[18], f_uv) * f_color;
if(index == 19) FragColor += texture(u_textures[19], f_uv) * f_color;
if(index == 20) FragColor += texture(u_textures[20], f_uv) * f_color;
if(index == 21) FragColor += texture(u_textures[21], f_uv) * f_color;
if(index == 22) FragColor += texture(u_textures[22], f_uv) * f_color;
if(index == 23) FragColor += texture(u_textures[23], f_uv) * f_color;
if(index == 24) FragColor += texture(u_textures[24], f_uv) * f_color;
if(index == 25) FragColor += texture(u_textures[25], f_uv) * f_color;
if(index == 26) FragColor += texture(u_textures[26], f_uv) * f_color;
if(index == 27) FragColor += texture(u_textures[27], f_uv) * f_color;
if(index == 28) FragColor += texture(u_textures[28], f_uv) * f_color;
if(index == 29) FragColor += texture(u_textures[29], f_uv) * f_color;
if(index == 30) FragColor += texture(u_textures[30], f_uv) * f_color;
if(index == 31) FragColor += texture(u_textures[31], f_uv) * f_color;
}

}

Я ожидал, что текстуры будут отображаться без каких-либо сбоев, в основном потому, что я перенес логику пакетной обработки текстур из своего 2D-рендерера. Я уверен, что мне не хватает чего-то простого. Я использую NVIDIA GeForce MX450 PCIe/SSE2.
glGetError() не сообщил об ошибках, а обратный вызов LWJGL OpenGL все время молчал. С помощью RenderDoc я проверил, что текстуры привязаны к правильным слотам.

Подробнее здесь: https://stackoverflow.com/questions/777 ... h-renderer
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • OpenGL: Qt3D.Renderer.OpenGL.Backend: невозможно найти подходящий текстурный блок для решения «diffuseTexture».
    Anonymous » » в форуме C++
    0 Ответы
    45 Просмотры
    Последнее сообщение Anonymous
  • Как объединить данные координат текстур многих различных объектов в один vbo для атласа текстур
    Anonymous » » в форуме JAVA
    0 Ответы
    36 Просмотры
    Последнее сообщение Anonymous
  • Kafka Streams и Spring Batch Conflict – «Необходимо указать имя задания», несмотря на Spring.batch.job.enabled: false
    Anonymous » » в форуме JAVA
    0 Ответы
    37 Просмотры
    Последнее сообщение Anonymous
  • Почему мой рендеринг openGL не работает, Python OpenGL
    Anonymous » » в форуме Python
    0 Ответы
    39 Просмотры
    Последнее сообщение Anonymous
  • OpenGL: наложение текстур с помощью вершинного шейдера
    Anonymous » » в форуме C++
    0 Ответы
    11 Просмотры
    Последнее сообщение Anonymous

Вернуться в «JAVA»