Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define M_PI 3.1415926535897932384626433832795
- const float infinity = 999999999.0;
- vec3 view_dir = vec3(0.0, -0.1, -1.0);
- vec3 view_pos = vec3(0.0, 3.5, 17.0);
- const int MAX_DEPTH = 10;
- const int NUM_OF_OBJECTS = 5;
- const int NUM_OF_LIGHTS = 1;
- const int samples = 1;
- const int MAX_FRAMES_BLEND = 200;
- const float GAMMA = 2.2;
- const float bias = 0.000001;
- const float minimum_collision_distance = 0.00001;
- const float fov = 90.0 * M_PI / 180.0;
- const float EV = 10.0;
- const float light_intensity_scale = 1.0;
- const float light_directionality = 0.999;
- const float alpha_for_diffCosW = 1000.0;
- struct Ray{
- vec3 m_dir;
- vec3 m_or;
- vec3 energy;
- float ior;
- };
- struct Material{
- vec3 color;
- float ambient;
- float spec;
- float emissivity;
- };
- struct Object{
- int type;
- vec3 pos;
- float radius;
- //type 0: circle
- //type 1: sphere
- //type 2: plane
- //type 3: triangle
- vec3 normal;
- Material mat;
- };
- float seed = 0.0;
- vec2 uv = vec2(0.0);
- float random() {
- return fract(sin(dot(uv, mat2(cos(iTime), sin(iTime), -sin(iTime), cos(iTime)) * vec2(12.9898, 78.233)) + seed++) * 43758.5453);
- }
- mat3 make_rot_matrix_from_normals(vec3 _u,vec3 _v){
- float c = dot(_u, _v);
- mat3 _R = mat3(-1.0);
- if (c == 1.0){
- return mat3(1.0);
- }
- if (c != 1.0){
- vec3 _a = cross(_u, _v);
- mat3 _a_cross = mat3(0.0);
- _a_cross[1][0] = -_a.z;
- _a_cross[2][0] = _a.y;
- _a_cross[0][1] = _a.z;
- _a_cross[2][1] = -_a.x;
- _a_cross[0][2] = -_a.y;
- _a_cross[1][2] = _a.x;
- mat3 a_cross_sq = _a_cross * _a_cross;
- _R = mat3(1.0) + _a_cross + a_cross_sq * (1.0 / (1.0 + c));
- }
- return _R;
- }
- vec3 diff_cos_weighted_direction(float _spec, vec3 _n){
- if (_spec == 1.0){
- return _n;
- }
- float m = pow(alpha_for_diffCosW, _spec * _spec);
- float _u = random();
- float _v = random();
- float cosT = pow(_u, 1.0 / (1.0 + m));
- float sinT = sqrt(1.0 - cosT * cosT);
- float phi = 2.0 * M_PI * _v;
- vec3 step1 = vec3(sinT * cos(phi), sinT * sin(phi), cosT);
- //rotate to normal plane
- vec3 rotated_vec = make_rot_matrix_from_normals(vec3(0.0, 0.0, 1.0), _n) * step1;
- return normalize(rotated_vec);
- }
- Ray create_new_ray(vec3 _dir, vec3 _pos){
- return Ray(_dir, _pos, vec3(1.0),1.0);
- }
- struct Light{
- vec3 pos;
- vec3 color;
- };
- Object scene[NUM_OF_OBJECTS];
- Object lights[NUM_OF_LIGHTS];
- vec3 interpolated_ray_dir(vec2 _xy, float w, float h){
- float aspect_ratio = w/h;
- float x = (2.0 * (_xy.x +0.5)/w - 1.0);
- float y = -(1.0-2.0*(_xy.y+0.5)/h)/aspect_ratio;
- float D = 1.0 / tan(fov/2.0);
- return normalize(vec3(x,y,0) + D * view_dir);
- }
- vec3 get_point_at_distance(Ray _ray, float d){
- return _ray.m_or + d * _ray.m_dir;
- }
- float intersect(Ray _ray, Object _obj){
- float d = infinity;
- if (_obj.type == 0 ) // circle
- {
- float d_t = dot(_obj.pos - _ray.m_or,_obj.normal)/dot(_obj.normal,_ray.m_dir);
- float ip_to_midpt = length(get_point_at_distance(_ray,d_t) - _obj.pos);
- if (ip_to_midpt < _obj.radius)
- {
- return d = d_t;
- }
- }
- if (_obj.type == 1){
- vec3 r_t_c = _ray.m_or - _obj.pos;
- float p1 = -dot(_ray.m_dir, r_t_c);
- float p2sqr = p1 * p1 - dot(r_t_c, r_t_c) + _obj.radius * _obj.radius;
- if (p2sqr < 0.0){
- return infinity;
- }
- float p2 = sqrt(p2sqr);
- float _d = min(p1 - p2, p1 + p2);
- return _d > 0.0? _d : infinity;
- }
- if (_obj.type == 2){
- float _N = dot(_obj.normal, _ray.m_dir);
- float _d = infinity;
- if (abs(_N) < bias){
- return infinity;
- }
- else{
- vec3 or_to_plane = _obj.pos - _ray.m_or;
- _d = dot(or_to_plane,_obj.normal) / _N;
- }
- if (_d > 0.0){
- return _d;
- }
- else{
- return infinity;
- }
- }
- return d;
- }
- vec3 get_normal(vec3 _point, Object _obj){
- vec3 n = vec3(0.0, 0.0, 1.0);
- if (_obj.type == 0){
- return normalize(_obj.normal);
- }
- if (_obj.type == 1){
- return normalize(_point - _obj.pos);
- }
- if (_obj.type == 2){
- return _obj.normal;
- }
- return n;
- }
- vec2 intersect_scene(inout Ray _ray, Object [NUM_OF_OBJECTS] _scene){
- float closest = infinity;
- int nearest_obj = -1;
- for(int i = 0; i< NUM_OF_OBJECTS; i++){
- float dist = intersect(_ray, _scene[i]);
- if (dist < closest){
- if(dist > minimum_collision_distance){
- closest = dist;
- nearest_obj = i;
- }
- }
- }
- return vec2(float(nearest_obj), closest);
- }
- vec3 trace(inout Ray _ray, Object [NUM_OF_OBJECTS] _scene, int _depth){
- vec3 acquired_color = vec3(0.0, 0.0, 0.0);
- if (_depth <= MAX_DEPTH){
- vec2 intersection_info = intersect_scene(_ray, _scene);
- int intersection_id = int(intersection_info.x);
- float intersection_distance = intersection_info.y;
- if (intersection_distance < infinity){
- float distance_sq = intersection_distance * intersection_distance;
- vec3 intersection_point = get_point_at_distance(_ray, intersection_distance);
- vec3 surf_norm = get_normal(intersection_point,_scene[intersection_id]);
- float n_dot_r = dot(surf_norm, _ray.m_dir);
- if (_scene[intersection_id].mat.emissivity > 0.0){
- return vec3(_scene[intersection_id].mat.emissivity) * _scene[intersection_id].mat.color;
- }
- //random ray towards light
- vec3 diffuse_direct_col = vec3(0.0);
- for(int k =0;k<1;k++){
- for(int i=0;i<NUM_OF_LIGHTS;i++){
- //make ray towards this light
- vec3 pt_to_light_vec0 = normalize(lights[i].pos - intersection_point);
- vec3 random_dir = diff_cos_weighted_direction(light_directionality, pt_to_light_vec0);
- Ray r_to_light = create_new_ray(random_dir, intersection_point + bias * surf_norm);
- vec2 towards_light_intersection_info = intersect_scene(r_to_light, _scene);
- int index_collision = int(towards_light_intersection_info.x);
- if(towards_light_intersection_info.y < infinity){
- if(_scene[index_collision].mat.emissivity > 0.0){
- float n_dot_li = dot(random_dir, surf_norm);
- if(n_dot_li > 0.0){
- float dist_to_light = length(lights[i].pos - intersection_point);
- float di_fo = 1.0/ (dist_to_light *dist_to_light ) * sqrt(light_directionality) + (1.0 - sqrt(light_directionality));
- diffuse_direct_col += n_dot_li * _scene[intersection_id].mat.color * lights[i].mat.emissivity * di_fo ;
- }
- }
- }
- }
- }
- acquired_color += diffuse_direct_col / float(samples);
- //reflect
- float dice = random();
- if (dice<_scene[intersection_id].mat.spec){
- //then it'll be reflective
- _ray.m_or = intersection_point + bias * surf_norm;
- _ray.m_dir = reflect(_ray.m_dir, surf_norm);
- _ray.energy *= _scene[intersection_id].mat.spec * _scene[intersection_id].mat.color ;
- }
- else{
- //it'll be diffuse
- _ray.m_or = intersection_point + bias * surf_norm;
- _ray.m_dir = diff_cos_weighted_direction( _scene[intersection_id].mat.spec, reflect(_ray.m_dir, surf_norm));
- _ray.energy *= _scene[intersection_id].mat.color * _scene[intersection_id].mat.ambient / (1.0 - _scene[intersection_id].mat.spec) ;
- }
- //direct point light
- vec3 light_pos = vec3(0.0, 15.0, 2.0);
- vec3 ligh_col = vec3(0.0);
- vec3 vec_to_light = normalize(light_pos - intersection_point);
- Ray light_ray = create_new_ray(vec_to_light, intersection_point);
- vec2 LR_intersect_data = intersect_scene(light_ray, _scene);
- if( LR_intersect_data.x < 0.0){
- float n_dot_lr = dot(vec_to_light, surf_norm);
- if(n_dot_lr > 0.0){
- float distance_to_light = length(light_pos - intersection_point);
- float distance_falloff = (4.0 * M_PI * distance_to_light *distance_to_light);
- acquired_color += light_intensity_scale * _scene[intersection_id].mat.color * n_dot_lr * ligh_col;
- }
- }
- }
- else{
- _ray.energy = vec3(0.0);
- return vec3(0.0);
- }
- }
- return acquired_color;
- }
- void make_scene(){
- float default_ambient = 0.18;
- //material: color amb spec em
- Material white = Material(vec3(1.0, 1.0, 1.0), default_ambient, 1.0, 1.0);
- Material matte_white = Material(vec3(1.0, 1.0, 1.0), default_ambient, 0.0, 0.0);
- Material purple = Material(vec3(1.0, 1.0, 1.0), default_ambient, 0.0, 0.0);
- vec3 disco_color = vec3((sin(iTime)+0.5), cos(iTime)+0.5, cos(iTime)*sin(iTime));
- Material disco = purple;
- Material red = Material(vec3(1.0, 0.0, 0.0), default_ambient, 0.0, 0.00);
- Material green = Material(vec3(0.0, 1.0, 0.0), default_ambient, 1.0, 0.0);
- //object
- //type pos radius normal material
- float lulz = 2.0;
- float freq = 0.0;
- scene[0] = Object(1, vec3(lulz*sin(iTime*freq), 2.0, -5.0), 1.0, vec3(0.0, 0.0, 0.0), white);
- scene[1] = Object(1, vec3(0.0, 0.0, 0.0), 1.0, vec3(0.0, 0.0, 0.0), disco);
- scene[2] = Object(2, vec3(0.0, -0.5, 0.0), infinity, vec3(0.0, 1.0, 0.0), matte_white);
- scene[3] = Object(1, vec3(-2.0, 0.0, 0.0), 1.0, vec3(0.0, 0.0, 0.0), red);
- scene[4] = Object(1, vec3(2.0, 0.0, 0.0), 1.0, vec3(0.0, 0.0, 0.0), green);
- lights[0] = scene[0];
- }
- void mainImage( out vec4 fragColor, in vec2 fragCoord )
- {
- // process_input();
- make_scene();
- // Normalized pixel coordinates (from 0 to 1)UV = fragCoord;
- seed=iTime;
- uv = fragCoord;
- float _w = iResolution.x;
- float _h = iResolution.y;
- vec3 ray_dir_from_view = interpolated_ray_dir(uv, _w,_h);
- Ray pixel_ray = Ray(ray_dir_from_view, view_pos, vec3(1.0),1.0);
- vec3 out_col = vec3(0.0);
- for(int k = 0; k< samples; k++){
- pixel_ray = Ray(ray_dir_from_view, view_pos, vec3(1.0),1.0);
- for(int i=0;i<MAX_DEPTH;i++){
- out_col += pixel_ray.energy * trace(pixel_ray, scene, i);
- seed++;
- }
- }
- //out_col /= float(samples);
- // blend with previous
- vec2 UV = fragCoord.xy / iResolution.xy;
- vec4 prev_col = texture(iChannel0, UV);
- float weight = 1.0;
- vec4 new_frag = vec4(prev_col.rgb + weight*out_col, prev_col.a + weight);
- if(!all(lessThanEqual(iMouse.zw, vec2(0.0)))){
- new_frag = vec4(out_col, 1.0);
- }
- // Output to screen
- fragColor = new_frag;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement