Skip to content

Commit

Permalink
start to refactor shaders into shader array
Browse files Browse the repository at this point in the history
  • Loading branch information
toloudis committed Dec 30, 2024
1 parent 89bf06a commit 120f01f
Show file tree
Hide file tree
Showing 7 changed files with 498 additions and 1 deletion.
8 changes: 7 additions & 1 deletion renderlib/graphics/glsl/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
target_include_directories(renderlib PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}"
)

add_subdirectory(shaders)

target_sources(renderlib PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/GLBasicVolumeShader.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/GLBasicVolumeShader.h"
Expand All @@ -17,5 +20,8 @@ target_sources(renderlib PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/GLFlatShader2D.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/GLFlatShader2D.h"
"${CMAKE_CURRENT_SOURCE_DIR}/GLImageShader2DnoLut.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/GLImageShader2DnoLut.h"
"${CMAKE_CURRENT_SOURCE_DIR}/GLImageShader2DnoLut.h"
"${CMAKE_CURRENT_SOURCE_DIR}/shaders.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/shaders.h"
)

36 changes: 36 additions & 0 deletions renderlib/graphics/glsl/shaders.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include "shaders.h"

#include "shaders/shader_gen.hpp"

static std::unordered_map<std::string, std::string> shader_src = { { "shader", shader_shader } };
static std::unordered_map<std::string, GLShader*> shaders;

bool
ShaderArray::BuildShaders()
{
for (auto& shader : shader_src) {
GLShader* s = new GLShader(GL_FRAGMENT_SHADER);
if (s->compileSourceCode(shader.second.c_str())) {
shaders[shader.first] = s;
} else {
LOG_ERROR << "Failed to compile shader " << shader.first;
return false;
}
}
return true;
}

GLShader*
ShaderArray::GetShader(const std::string& name)
{
return shaders[name];
}

void
ShaderArray::DestroyShaders()
{
for (auto& shader : shaders) {
delete shader.second;
}
shaders.clear();
}
11 changes: 11 additions & 0 deletions renderlib/graphics/glsl/shaders.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once

#include "gl/Util.h"

class ShaderArray
{
public:
static bool BuildShaders();
static GLShader* GetShader(const std::string& name);
static void DestroyShaders();
};
29 changes: 29 additions & 0 deletions renderlib/graphics/glsl/shaders/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
function(convert_shader_to_cpp input_file output_file)
# Read the shader file content
file(READ "${input_file}" shader_content)

# Escape special characters in the shader content
#string(REGEX REPLACE "\\" "\\\\" shader_content "${shader_content}")
#string(REGEX REPLACE "\"" "\\\"" shader_content "${shader_content}")
#string(REGEX REPLACE "\n" "\\n" shader_content "${shader_content}")
string(REPLACE "." "_" output_file "${output_file}")

# Generate the C++ file content
set(cpp_content "
#include <string>
const std::string ${output_file}_shader = R\"(
${shader_content}
)\";
")

# Write the C++ file
file(WRITE "${output_file}_gen.hpp" "${cpp_content}")
endfunction()

# Convert your shader file
convert_shader_to_cpp("shader.frag" "shader")

# Add the generated C++ file to your target
target_sources(renderlib PRIVATE shader_gen.hpp)
200 changes: 200 additions & 0 deletions renderlib/graphics/glsl/shaders/shader.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
#version 400 core

in VertexData
{
vec3 pObj;
} inData;

out vec4 outputColour;

uniform mat4 inverseModelViewMatrix;

uniform sampler3D textureAtlas;
uniform sampler2D textureAtlasMask;
//uniform sampler2D lut;

#define M_PI 3.14159265358979323846
uniform vec2 iResolution;
uniform float isPerspective;
uniform float orthoScale;
uniform float GAMMA_MIN;
uniform float GAMMA_MAX;
uniform float GAMMA_SCALE;
uniform float BRIGHTNESS;
uniform float DENSITY;
uniform float maskAlpha;
uniform int BREAK_STEPS;
uniform vec3 AABB_CLIP_MIN;
uniform vec3 AABB_CLIP_MAX;
uniform vec3 flipVolumeAxes;

uniform float dataRangeMin; // 0..1 (mapped from 0..uint16_max)
uniform float dataRangeMax; // 0..1 (mapped from 0..uint16_max)

uniform vec4 g_clipPlane;

float powf(float a, float b) {
return pow(a, b);
}

float rand(vec2 co) {
float threadId = gl_FragCoord.x / (gl_FragCoord.y + 1.0);
float bigVal = threadId*1299721.0 / 911.0;
vec2 smallVal = vec2(threadId*7927.0 / 577.0, threadId*104743.0 / 1039.0);
return fract(sin(dot(co, smallVal)) * bigVal);
}

vec4 luma2Alpha(vec4 color, float vmin, float vmax, float C) {
float x = max(color[2], max(color[0], color[1]));
float xi = (x - vmin) / (vmax - vmin);
xi = clamp(xi, 0.0, 1.0);
float y = pow(xi, C);
y = clamp(y, 0.0, 1.0);
color[3] = y;
return(color);
}

vec4 sampleAs3DTexture(sampler3D tex, vec4 pos) {
float bounds = float(pos[0] > 0.001 && pos[0] < 0.999 &&
pos[1] > 0.001 && pos[1] < 0.999 &&
pos[2] > 0.001 && pos[2] < 0.999);

vec4 texval = textureLod(tex, pos.xyz*flipVolumeAxes, 0).rgba;
vec4 retval = vec4(texval.rgb, 1.0);

// float texval = textureLod(tex, pos.xyz, 0).r;
// texval = (texval - dataRangeMin) / (dataRangeMax - dataRangeMin);
// vec4 retval = vec4(texval, texval, texval, 1.0);
return bounds*retval;
}

vec4 sampleStack(sampler3D tex, vec4 pos) {
vec4 col = sampleAs3DTexture(tex, pos);
col = luma2Alpha(col, GAMMA_MIN, GAMMA_MAX, GAMMA_SCALE);
return col;
}

//->intersect AXIS-ALIGNED box routine
//
bool intersectBox(in vec3 r_o, in vec3 r_d, in vec3 boxMin, in vec3 boxMax, out float tnear, out float tfar) {
vec3 invR = vec3(1.0, 1.0, 1.0) / r_d;
vec3 tbot = invR * (boxMin - r_o);
vec3 ttop = invR * (boxMax - r_o);
vec3 tmin = min(ttop, tbot);
vec3 tmax = max(ttop, tbot);
float largest_tmin = max(max(tmin.x, tmin.y), max(tmin.x, tmin.z));
float smallest_tmax = min(min(tmax.x, tmax.y), min(tmax.x, tmax.z));
tnear = largest_tmin;
tfar = smallest_tmax;

// now constrain near and far using clipPlane if active.
// plane xyz is normal, plane w is -distance from origin.
float denom = dot(r_d, g_clipPlane.xyz);
if (abs(denom) > 0.0001f) // your favorite epsilon
{
float tClip = dot(g_clipPlane.xyz*(-g_clipPlane.w) - r_o, g_clipPlane.xyz) / denom;
if (denom < 0.0f) {
tnear = max(tnear, tClip);
}
else {
tfar = min(tfar, tClip);
}
}
else
{
// todo check to see which side of the plane we are on ?
}


return(tfar > tnear);
}

vec4 integrateVolume(vec4 eye_o, vec4 eye_d,
float tnear, float tfar,
float clipNear, float clipFar,
sampler3D textureAtlas
) {
vec4 C = vec4(0.0);
float tend = min(tfar, clipFar);
float tbegin = tnear;
const int maxSteps = 512;
float csteps = clamp(float(BREAK_STEPS), 1.0, float(maxSteps));
float invstep = 1.0 / csteps;
float r = 0.5 - 1.0*rand(eye_d.xy);
float tstep = invstep;
float tfarsurf = r*tstep;
float overflow = mod((tfarsurf - tend), tstep);
float t = tbegin + overflow;
t += r*tstep;
float tdist = 0.0;
int numSteps = 0;

vec4 pos, col;
float s = 0.5 * float(maxSteps) / csteps;
for (int i = 0; i<maxSteps; i++) {
pos = eye_o + eye_d*t;
pos.xyz = (pos.xyz + 0.5);//0.5 * (pos + 1.0); // map position from [boxMin, boxMax] to [0, 1] coordinates
col = sampleStack(textureAtlas, pos);

//Finish up by adding brightness/density
col.xyz *= BRIGHTNESS;
col.w *= DENSITY;
float stepScale = (1.0 - powf((1.0 - col.w), s));
col.w = stepScale;
col.xyz *= col.w;
col = clamp(col, 0.0, 1.0);

C = (1.0 - C.w)*col + C;
t += tstep;
numSteps = i;
if (t > tend)
break;
if (C.w > 1.0)
break;
}
return C;
}
void main()
{
outputColour = vec4(1.0, 0.0, 0.0, 1.0);
// gl_FragCoord defaults to 0,0 at lower left
vec2 vUv = gl_FragCoord.xy/iResolution.xy;

vec3 eyeRay_o, eyeRay_d;
if (isPerspective != 0.0) {
// camera position in camera space is 0,0,0!
eyeRay_o = (inverseModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
eyeRay_d = normalize(inData.pObj - eyeRay_o);
}
else {
float zDist = 2.0;
eyeRay_d = (inverseModelViewMatrix*vec4(0.0, 0.0, -zDist, 0.0)).xyz;
vec4 ray_o = vec4(2.0*vUv - 1.0, 1.0, 1.0);
ray_o.xy *= orthoScale;
ray_o.x *= iResolution.x/iResolution.y;
eyeRay_o = (inverseModelViewMatrix*ray_o).xyz;
}

vec3 boxMin = AABB_CLIP_MIN;
vec3 boxMax = AABB_CLIP_MAX;
float tnear, tfar;
bool hit = intersectBox(eyeRay_o, eyeRay_d, boxMin, boxMax, tnear, tfar);
if (!hit) {
outputColour = vec4(1.0, 0.0, 1.0, 0.0);
return;
}
//else {
// outputColour = vec4(1.0, 1.0, 1.0, 1.0);
// return;
//}
float clipNear = 0.0;//-(dot(eyeRay_o.xyz, eyeNorm) + dNear) / dot(eyeRay_d.xyz, eyeNorm);
float clipFar = 10000.0;//-(dot(eyeRay_o.xyz,-eyeNorm) + dFar ) / dot(eyeRay_d.xyz,-eyeNorm);

vec4 C = integrateVolume(vec4(eyeRay_o, 1.0), vec4(eyeRay_d, 0.0),
tnear, tfar,
clipNear, clipFar,
textureAtlas);
C = clamp(C, 0.0, 1.0);
outputColour = C;
return;
}
Loading

0 comments on commit 120f01f

Please sign in to comment.