[ATTACH=CONFIG]1922[/ATTACH] [ATTACH=CONFIG]1923[/ATTACH] [ATTACH=CONFIG]1924[/ATTACH]
I’m trying to write a raytracer using OpenGL fragment shader and having a problem with strange looking circular artifacts on boxes’ surfaces. :doh: I suspect that the problems with rand() and/or scatter() can be responsible for this.
#version 330 core
//#extension GL_ARB_gpu_shader_fp64 : require
//#define float double
//#define vec3 dvec3
//precision highp float;
in vec2 vTexcoord;
out vec4 FragColor;
uniform float uTime;
uniform mat4 uViewMatrix;
uniform ivec2 uResolution;
//////////////////////////////////////////////////
#define MAX_RAY_LENGTH 1000.0
#define FOV 70.0
struct Ray {
vec3 origin;
vec3 direction;
};
struct Material {
vec4 albedo;
};
struct Hit {
Material material;
vec3 position;
vec3 normal;
};
struct Box {
Material material;
vec3 min;
vec3 max;
};
Material red_lambert_material = Material(vec4(0.9, 0.2, 0.1, 1.0));
Material green_lambert_material = Material(vec4(0.2, 0.8, 0.1, 1.0));
Material blue_lambert_material = Material(vec4(0.1, 0.2, 0.8, 1.0));
Material purple_lambert_material = Material(vec4(0.5, 0.2, 0.7, 1.0));
Box BOXES[] = {
Box(red_lambert_material, vec3(-5.0, -1.0, -5.0), vec3(5.0, 0.0, 5.0)),
Box(green_lambert_material, vec3(-0.5, 0.0, -0.5), vec3(0.5, 1.0, 0.5)),
Box(blue_lambert_material, vec3(0.5, 0.0, 0.5), vec3(1.5, 1.0, 1.5)),
Box(purple_lambert_material, vec3(-0.25, 0.5, 2.0), vec3(0.25, 1.0, 2.5))
};
float rand(in vec2 seed) {
return 2*fract(sin(dot(seed, vec2(12.9898,78.233)))*43758.5453) - 1;
}
bool scatter(in Hit hit, out Ray ray, out vec3 attenuation) {
attenuation = hit.material.albedo.rgb;
vec3 direction = hit.normal + vec3(rand(hit.position.xy), rand(hit.position.zy), rand(hit.position.xz));
ray = Ray(hit.position, direction);
return true;
}
vec2 intersect_box(in Ray ray, in Box box) {
vec3 t_min = (box.min - ray.origin) / ray.direction;
vec3 t_max = (box.max - ray.origin) / ray.direction;
vec3 t1 = min(t_min, t_max);
vec3 t2 = max(t_min, t_max);
float t_near = max(max(t1.x, t1.y), t1.z);
float t_far = min(min(t2.x, t2.y), t2.z);
return vec2(t_near, t_far);
}
bool intersect_world(in Ray ray, out Hit hit) {
float smallest = MAX_RAY_LENGTH;
bool found = false;
for(int i=0; i<BOXES.length(); i++) {
vec2 lambda = intersect_box(ray, BOXES[i]);
if(lambda.x > 0.0 && lambda.x < lambda.y && lambda.x < smallest) {
hit.material = BOXES[i].material;
hit.position = ray.origin + ray.direction*(lambda.x);
hit.normal = ivec3((hit.position-(BOXES[i].min+BOXES[i].max)/2.0) / (abs(BOXES[i].min-BOXES[i].max)/2.0));
smallest = lambda.x;
found = true;
}
}
return found;
}
vec3 trace(in Ray ray) {
Hit hit;
vec3 color = vec3(0, 0, 0);
vec3 total_attenuation = vec3(1.0, 1.0, 1.0);
for(int bounce=0; bounce<4; bounce++) {
if(intersect_world(ray, hit)) {
vec3 attenuation;
if(scatter(hit, ray, attenuation)) {
total_attenuation *= attenuation;
} else {
total_attenuation *= vec3(0,0,0);
}
} else {
vec3 unit_dir = normalize(ray.direction);
float t = 0.5 * (unit_dir.y + 1.0);
color = total_attenuation * ((1.0-t)*vec3(1.0,1.0,1.0)+t*vec3(0.5,0.7,1.0));
break;
}
}
return color;
}
Ray get_ray(in vec2 texcoord) {
float h = tan(radians((float(uResolution.x)/float(uResolution.y))*FOV)/2.0);
float v = tan(radians(FOV)/2.0);
vec3 origin = (uViewMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
vec3 dir = normalize(vec3(mix(-h, h, texcoord.x), mix(-v, v, texcoord.y), -1.0));
dir = (uViewMatrix * vec4(dir, 0.0)).xyz;
return Ray(origin, dir);
}
void main() {
BOXES[2].min.y = 1.0+sin(radians(uTime/11.11))+1.0;
BOXES[2].max.y = 2.0+sin(radians(uTime/11.11))+1.0;
BOXES[3].min.x = -0.25+3.0*sin(radians(uTime/11.11));
BOXES[3].max.x = 0.25+3.0*sin(radians(uTime/11.11));
BOXES[3].min.z = -0.25+3.0*cos(radians(uTime/11.11));
BOXES[3].max.z = 0.25+3.0*cos(radians(uTime/11.11));
vec3 color = vec3(0.0);
int samples = 16;
for(int sample=0; sample < samples; sample++) {
Ray ray = get_ray(vTexcoord+vec2(rand(vec2(color.r, sample))-0.5)/vec2(uResolution));
color += trace(ray);
}
color /= samples;
FragColor = vec4(color, 1.0);
}
I’ve tried to fix this by using GL_ARB_gpu_shader_fp64 extension, but even when every float is replaced with double, there is always a small circular artifact on every surface. :tired: