LWJGL Forum

Programming => OpenGL => Topic started by: Imagyx on February 10, 2021, 21:40:25

Title: Need help with offscreen rendering
Post by: Imagyx on February 10, 2021, 21:40:25
Hello everyone.

I wanted to give it a try and switch from CPU-Raytracing with Java to using OpenGL and therefore LWJGL.
I've searched for days about one problem I cannot solve concerning the size of an image I want to save.
I setup GLFW and everything neccessary for a compute shader to render me  a simple scene on screen, which works   :)
But when I want to save into a BufferedImage bigger than my screen size, a part of the image is left black.
I read a lot about using glViewport, disabling GL_SCISSOR_TEST, using Renderbuffer and  I tried all of that with no better results.

I would appreciate it a lot if someone can help me with that, as I think that this is a simple question for any pro used to these kinds of things for a long time.
I know that I don't know much about OpenGL yet, still I want to keep going since the speedup is 1000x and more from my CPU tracer to what I have no with the GPU.
Thank you in advance for any help.


This is my setup:
Code: [Select]
createOffscreen();
int framebuffer = initShaders();
resetShaders();
glViewport(0, 0, width, height); // 3000x2040 e.g.
glDisable(GL_SCISSOR_TEST);
tracing();
saveImage(framebuffer);

with methods

Code: [Select]
private void createOffscreen() {
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
long offscreen = glfwCreateWindow(width, height, "", NULL, NULL);
glfwMakeContextCurrent(offscreen);
createCapabilities();
}
private void saveImage(int framebuffer) {
glReadBuffer(framebuffer);
int bpp = 4; //RGBA
ByteBuffer buffer = BufferUtils.createByteBuffer(width * height * bpp);
GL11.glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
BufferedImage offscreen = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for(int x = 0; x < width; x++){
    for(int y = 0; y < height; y++){
        int i = (x + (width * y)) * bpp;
        int r = buffer.get(i) & 0xFF;
        int g = buffer.get(i + 1) & 0xFF;
        int b = buffer.get(i + 2) & 0xFF;
        offscreen.setRGB(x, height - (y + 1), (0xFF << 24) | (r << 16) | (g << 8) | b);
    }
}
...ImageIO.write....
}
private void resetShaders() {
glShaderSource(quadProgramVs, templating(VERTEX_SHADER ,vertexShader.getText()));
glCompileShader(quadProgramVs);

glShaderSource(quadProgramFs, templating(FRAGMENT_SHADER, fragmentShader.getText()));
glCompileShader(quadProgramFs);

glLinkProgram(quadProgram);

glShaderSource(computeProgramShader, templating(COMPUTE_SHADER, computeShader.getText()));
glCompileShader(computeProgramShader);

glLinkProgram(computeProgram);

numGroupsX = (int) Math.ceil((double) width / 8);
numGroupsY = (int) Math.ceil((double) height / 8);
}

private int initShaders() {
glBindVertexArray(glGenVertexArrays());

int framebuffer = glGenTextures();
glBindTexture(GL_TEXTURE_2D, framebuffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
glBindImageTexture(0, framebuffer, 0, false, 0, GL_WRITE_ONLY, GL_RGBA8);

// Create program to render framebuffer texture as fullscreen quad
quadProgram = glCreateProgram();

quadProgramVs = glCreateShader(GL_VERTEX_SHADER);
glAttachShader(quadProgram, quadProgramVs);

quadProgramFs = glCreateShader(GL_FRAGMENT_SHADER);
glAttachShader(quadProgram, quadProgramFs);

// Create ray tracing compute shader
computeProgram = glCreateProgram();
computeProgramShader = glCreateShader(GL_COMPUTE_SHADER);
glAttachShader(computeProgram, computeProgramShader);

return framebuffer;
}

private void tracing() {
// Trace the scene
glUseProgram(computeProgram);
glDispatchCompute(numGroupsX, numGroupsY, 1);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);

glUseProgram(quadProgram);
glDrawArrays(GL_TRIANGLES, 0, 3);
}