HI
So, I want to try the compute shader to calculate transfer functions on my 3D texture, and output a new 3D texture, but I cant get it to work at all… Nothing happens. Right now I am just trying to fill the whole new 3D texture (outVolumeTexture) with values of 100.0. If I try to put in a nullptr as data for outVolumeTexture, the result is still empty. If I put in pData, the resulting 3d texture is just pData (it doesnt get changed).
Here is my volume renderer. I am calling the compute shader in my constructor. Is this a problem? Or is it something with the formats of my 3D textures? Or am I forgetting something?
GLSL SHADER:
#version 450
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
layout(r32f, binding = 0) uniform image3D inputVolumeImage;
layout(r32f, binding = 1) uniform image3D outputVolumeImage;
//layout(r32ui, binding = 2) uniform uimage2D outputHistogramImage;
void main(void)
{
ivec3 coord = ivec3(gl_GlobalInvocationID);
imageStore(outputVolumeImage, coord, vec4(100.0, 100.0, 100.0, 100.0));
RENDERING FILE (.cpp):
#include "VolumeRenderer.h"
#include <globjects/base/File.h>
#include <iostream>
#include "Viewer.h"
using namespace dynamol;
using namespace gl;
using namespace glm;
using namespace globjects;
VolumeRenderer::VolumeRenderer(Viewer* viewer, bool isVR) : Renderer(viewer, isVR)
{
if (isVR) {
viewportSize = (ivec2)viewer->renderTargetSize();
}
else {
viewportSize = viewer->viewportSize();
}
// Load shaders and attach to program
// MAIN RENDER SHADER
m_program = globjects::Program::create();
m_vertexShaderSource = Shader::sourceFromFile("./../res/volume/volume-vs.glsl");
m_fragmentShaderSource = Shader::sourceFromFile("./../res/volume/volume-fs.glsl");
m_vertexShader = Shader::create(GL_VERTEX_SHADER, m_vertexShaderSource.get());
m_fragmentShader = Shader::create(GL_FRAGMENT_SHADER, m_fragmentShaderSource.get());
m_program->attach(m_vertexShader.get(), m_fragmentShader.get());
// Build quad to fill screen
m_quadVertices->setStorage(std::array<vec2, 4>({ vec2(-1.0f, 1.0f), vec2(-1.0f, -1.0f), vec2(1.0f, 1.0f), vec2(1.0f, -1.0f) }), gl::GL_NONE_BIT);
auto vertexBindingQuad = m_quadArray->binding(0); //bind buffer 0
vertexBindingQuad->setBuffer(m_quadVertices.get(), 0, sizeof(vec2)); //point at the array above, start at 0, stride of vec2
vertexBindingQuad->setFormat(2, GL_FLOAT);
m_quadArray->enable(0);
m_quadArray->unbind();
// Load data, create and bind source 3D texture
unsigned short uWidth = viewer->scene()->volume()->uWidth;
unsigned short uHeight = viewer->scene()->volume()->uHeight;
unsigned short uDepth = viewer->scene()->volume()->uDepth;
unsigned short* pData = viewer->scene()->volume()->pData;
volumeTexture = Texture::create(GL_TEXTURE_3D);
volumeTexture->setParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
volumeTexture->setParameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
volumeTexture->setParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
volumeTexture->setParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
volumeTexture->setParameter(GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER);
volumeTexture->image3D(0, GL_R32F, ivec3(uWidth, uHeight, uDepth), 0, GL_RED, GL_UNSIGNED_SHORT, pData);
// COMPUTE SHADER
m_computeProgram = globjects::Program::create();
m_computeShaderSource = Shader::sourceFromFile("./../res/volume/volume-cs.glsl");
m_computeShader = Shader::create(GL_COMPUTE_SHADER, m_computeShaderSource.get());
m_computeProgram->attach(m_computeShader.get());
// Create and bind output 3D texture
outVolumeTexture = Texture::create(GL_TEXTURE_3D);
outVolumeTexture->setParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
outVolumeTexture->setParameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
outVolumeTexture->setParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
outVolumeTexture->setParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
outVolumeTexture->setParameter(GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER);
outVolumeTexture->image3D(0, GL_R32F, ivec3(uWidth, uHeight, uDepth), 0, GL_RED, GL_UNSIGNED_SHORT, pData);
// Create and bind output histogram texture
outHistogramTexture = Texture::create(GL_TEXTURE_2D);
outHistogramTexture->setParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
outHistogramTexture->setParameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
outHistogramTexture->setParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
outHistogramTexture->setParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
outHistogramTexture->image2D(0, GL_R32F, ivec2(512, 512), 0, GL_RED, GL_UNSIGNED_SHORT , nullptr);
int groupSizeX = 1, groupSizeY = 1, groupSizeZ = 1;
int numGroupsX = ceilf(float(uWidth) / float(groupSizeX));
int numGroupsY = ceilf(float(uHeight) / float(groupSizeY));
int numGroupsZ = ceilf(float(uDepth) / float(groupSizeZ));
m_computeProgram->use();
m_computeProgram->setUniform("inputVolumeImage", 0);
volumeTexture->bindActive(0);
m_computeProgram->setUniform("outputVolumeImage", 1);
outVolumeTexture->bindActive(1);
//m_computeProgram->setUniform("outputHistogramImage", 2);
//outHistogramTexture->bindActive(2);
m_computeProgram->dispatchCompute(uWidth, uHeight, uDepth);
glMemoryBarrier(GL_ALL_BARRIER_BITS);
m_computeProgram->release();
volumeTexture->unbind();
outVolumeTexture->unbind();
outHistogramTexture->unbind();
}
std::list<globjects::File*> VolumeRenderer::shaderFiles() const
{
return std::list<globjects::File*>({
m_vertexShaderSource.get(),
m_fragmentShaderSource.get()
});
}
void VolumeRenderer::display()
{
// SaveOpenGL state
auto currentState = State::currentState();
// Set background color
glm::vec3 m_backgroundColor = viewer()->backgroundColor();
// Update matrices
const mat4 projectionMatrix = viewer()->projectionTransform();
const mat4 viewMatrix = viewer()->viewTransform();
const mat4 modelMatrix = viewer()->modelTransform();
const mat4 modelViewMatrix = viewMatrix * modelMatrix;
const mat4 modelViewProjectionMatrix = projectionMatrix * modelViewMatrix;
const mat4 inverseModelViewProjectionMatrix = inverse(modelViewProjectionMatrix);
// BIND FRAMEBUFFER
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Set OpenGL parameters
glViewport(0, 0, viewportSize.x, viewportSize.y);
glClearDepth(1.0f);
glClearColor(0.0, 0.0, 0.0, 65535.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
// set shader parameters
m_program->setUniform("modelViewProjectionMatrix", modelViewProjectionMatrix);
m_program->setUniform("inverseModelViewProjectionMatrix", inverseModelViewProjectionMatrix);
m_program->setUniform("maxNumberOfSteps", maxNumberOfSteps);
m_program->setUniform("minimumHitDistance", minimumHitDistance);
m_program->setUniform("maximumTraceDistance", maximumTraceDistance);
m_program->setUniform("lightPosition", lightPosition);
m_program->setUniform("lightColor", lightColor);
m_program->setUniform("volumeTexture", 1);
outVolumeTexture->bindActive(1);
m_quadArray->bind();
m_program->use();
// Render a screen filling quad (as a triangle strip), so we can cast rays for every pixel
m_quadArray->drawArrays(gl::GL_TRIANGLE_STRIP, 0, 4);
m_program->release();
m_quadArray->unbind();
outVolumeTexture->unbind();
glDisable(GL_BLEND);
glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
currentState->apply();
}
void VolumeRenderer::displayVR()
{
viewportSize = ivec2(vec2(viewer()->renderTargetSize()));
display();
}