# HG changeset patch # User John Tsiombikas # Date 1415575560 -7200 # Node ID 2ed3da7dc0bcaa3f710e0400ddfe0ac9a06dfed2 # Parent 297dbc5080c47d80a0a1a7119621f836e8f55a6b broken diff -r 297dbc5080c4 -r 2ed3da7dc0bc gpuray_glsl.vcxproj --- a/gpuray_glsl.vcxproj Sun Nov 09 20:13:33 2014 +0200 +++ b/gpuray_glsl.vcxproj Mon Nov 10 01:26:00 2014 +0200 @@ -96,6 +96,7 @@ + @@ -127,6 +128,7 @@ + diff -r 297dbc5080c4 -r 2ed3da7dc0bc gpuray_glsl.vcxproj.filters --- a/gpuray_glsl.vcxproj.filters Sun Nov 09 20:13:33 2014 +0200 +++ b/gpuray_glsl.vcxproj.filters Mon Nov 10 01:26:00 2014 +0200 @@ -124,6 +124,9 @@ imago + + src + @@ -210,6 +213,9 @@ imago + + src + diff -r 297dbc5080c4 -r 2ed3da7dc0bc sdr/rt.glsl --- a/sdr/rt.glsl Sun Nov 09 20:13:33 2014 +0200 +++ b/sdr/rt.glsl Mon Nov 10 01:26:00 2014 +0200 @@ -46,6 +46,13 @@ struct Material mat; }; +struct Cone { + float index; + float angle; + float start, end; + struct Material mat; +}; + struct Light { vec3 pos, color; }; @@ -55,6 +62,7 @@ bool sphere_intersect(in Sphere sph, in Ray ray, out HitPoint pt); bool plane_intersect(in Plane plane, in Ray ray, out HitPoint pt); bool box_intersect(in Box box, in Ray ray, out HitPoint pt); +bool cone_intersect(in Cone cone, in Ray ray, out HitPoint pt); vec3 transform(in vec3 v, in mat4 inv_xform); Ray transform(in Ray ray, in mat4 xform, in mat4 inv_xform); Ray get_primary_ray(); @@ -62,11 +70,12 @@ Sphere read_sphere(in float idx); Plane read_plane(in float idx); Box read_box(in float idx); +Cone read_cone(in float idx); Material read_material(in sampler2D tex, in float ty); void read_xform(in float idx, out mat4 xform, out mat4 inv_xform); uniform sampler2D tex_raydir; -uniform sampler2D tex_spheres, tex_planes, tex_boxes; +uniform sampler2D tex_spheres, tex_planes, tex_boxes, tex_cones; uniform sampler2D tex_megatex; uniform sampler2D tex_xforms; uniform samplerCube tex_env; @@ -75,8 +84,8 @@ uniform Light lights[8]; uniform int num_lights; -int num_spheres, num_planes, num_boxes; -float sph_tex_sz, plane_tex_sz, box_tex_sz, xform_tex_sz; +int num_spheres, num_planes, num_boxes, num_cones; +float sph_tex_sz, plane_tex_sz, box_tex_sz, cone_tex_sz, xform_tex_sz; #ifdef INIT_EVERYTHING Material default_material; @@ -108,6 +117,10 @@ num_boxes = int(desc.x); box_tex_sz = desc.y; + desc = texture2D(tex_cones, vec2(0.0, 0.0)); + num_cones = int(desc.x); + cone_tex_sz = desc.y; + xform_tex_sz = texture2D(tex_xforms, vec2(0.0, 0.0)).x; @@ -215,6 +228,16 @@ } } + for(int i=0; i= cone.end) { + return false; + } + + float radius = pt.pos.y * slope; + pt.normal = vec3(pt.pos.x, 0.0, pt.pos.z) / radius; + + float ny = sin(cone.angle); + float xzlen = sqrt(1.0 - ny * ny); + pt.normal.x *= xzlen; + pt.normal.y = ny; + pt.normal.z *= xzlen; + + pt.mat = cone.mat; + + pt.texcoord.x = 0.5 * atan(pt.normal.z, pt.normal.x) / M_PI + 0.5; + pt.texcoord.y = (pt.pos.y - cone.start) / (cone.end - cone.start); + +#ifdef USE_XFORM + pt.pos = (xform * vec4(pt.pos, 1.0)).xyz; + pt.normal = normalize(transform(pt.normal, xform)); +#endif + return true; +} + vec3 transform(in vec3 v, in mat4 xform) { return mat3(xform) * v; @@ -489,6 +583,22 @@ return box; } +Cone read_cone(in float idx) +{ + Cone cone; + float ty = (idx + 1.0) / cone_tex_sz; + + cone.index = texture2D(tex_cones, vec2(ITEM(0), ty)).x; + + vec4 texel = texture2D(tex_cones, vec2(ITEM(1), ty)); + cone.angle = texel.x; + cone.start = texel.y; + cone.end = texel.z; + + cone.mat = read_material(tex_cones, ty); + return cone; +} + void read_xform(in float idx, out mat4 xform, out mat4 inv_xform) { float ty = (idx + 1.0) / xform_tex_sz; diff -r 297dbc5080c4 -r 2ed3da7dc0bc src/cone.cc --- a/src/cone.cc Sun Nov 09 20:13:33 2014 +0200 +++ b/src/cone.cc Mon Nov 10 01:26:00 2014 +0200 @@ -65,10 +65,20 @@ pt->dist = t; pt->pos = ray.origin + ray.dir * t; - pt->normal.z = sin(angle); + if(pt->pos.y < ymin || pt->pos.y >= ymax) { + return false; + } - //pt->normal = (pt->pos - pos) / radius; TODO continue here + float radius = pt->pos.y * slope; + pt->normal = Vector3(pt->pos.x, 0.0, pt->pos.z) / radius; + + float ny = sin(angle); + float xzlen = sqrt(1.0 - ny * ny); + pt->normal.x *= xzlen; + pt->normal.y = ny; + pt->normal.z *= xzlen; pt->pos.transform(xform); pt->normal.transform(dir_xform); + return true; } diff -r 297dbc5080c4 -r 2ed3da7dc0bc src/gpuscene.cc --- a/src/gpuscene.cc Sun Nov 09 20:13:33 2014 +0200 +++ b/src/gpuscene.cc Mon Nov 10 01:26:00 2014 +0200 @@ -35,10 +35,12 @@ Sphere *sph; Plane *plane; Box *box; + Cone *cone; std::vector spheres; std::vector planes; std::vector boxes; + std::vector cones; // collect all objects into the different type-specific arrays for(auto obj : objects) { @@ -51,6 +53,9 @@ } else if((box = dynamic_cast(obj))) { boxes.push_back(box); + } else if((cone = dynamic_cast(obj))) { + cones.push_back(cone); + } else { fprintf(stderr, "skipping object of unknown type: %s\n", obj->get_name()); } @@ -59,6 +64,7 @@ create_sphere_texture(spheres); create_plane_texture(planes); create_box_texture(boxes); + create_cone_texture(cones); create_env_texture(); create_xform_texture(); @@ -194,6 +200,38 @@ delete [] pixels; } +void GPUScene::create_cone_texture(const std::vector &cones) +{ + int xsz = OBJ_LINE_WIDTH; + int ysz = (int)cones.size() + 1; + int tex_ysz = next_pow2(ysz); + + Vector4 *pixels = new Vector4[xsz * tex_ysz]; + + pixels[0].x = (float)ysz; + pixels[0].y = (float)tex_ysz; + + Vector4 *pixptr = pixels + xsz; + + for(size_t i=0; iangle; + pixptr[1].y = cones[i]->ymin; + pixptr[1].z = cones[i]->ymax; + pixptr[1].w = 0.0; + + copy_material(pixptr, &cones[i]->material); + pixptr += OBJ_LINE_WIDTH; + } + + glBindTexture(GL_TEXTURE_2D, textures[TEX_SPHERE]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, xsz, tex_ysz, 0, GL_RGBA, GL_FLOAT, pixels); + + delete [] pixels; +} + + void GPUScene::create_megatexture() { // at least a 1x1 dummy white texture diff -r 297dbc5080c4 -r 2ed3da7dc0bc src/gpuscene.h --- a/src/gpuscene.h Sun Nov 09 20:13:33 2014 +0200 +++ b/src/gpuscene.h Mon Nov 10 01:26:00 2014 +0200 @@ -6,10 +6,11 @@ #include "sphere.h" #include "plane.h" #include "box.h" +#include "cone.h" class GPUScene : public Scene { public: - enum { TEX_SPHERE, TEX_PLANE, TEX_BOX, TEX_TEXTURE, TEX_ENV, TEX_XFORM, NUM_TEXTURES }; + enum { TEX_SPHERE, TEX_PLANE, TEX_BOX, TEX_CONE, TEX_TEXTURE, TEX_ENV, TEX_XFORM, NUM_TEXTURES }; private: unsigned int textures[NUM_TEXTURES]; @@ -20,6 +21,7 @@ void create_sphere_texture(const std::vector &spheres); void create_plane_texture(const std::vector &planes); void create_box_texture(const std::vector &box); + void create_cone_texture(const std::vector &cones); void create_megatexture(); void create_env_texture(); void create_xform_texture(); diff -r 297dbc5080c4 -r 2ed3da7dc0bc src/rend.cc --- a/src/rend.cc Sun Nov 09 20:13:33 2014 +0200 +++ b/src/rend.cc Mon Nov 10 01:26:00 2014 +0200 @@ -1,4 +1,6 @@ +#include #include +#include #include "scene.h" #include "image.h" #include "rend.h" @@ -10,6 +12,7 @@ TEX_SPHERES, TEX_PLANES, TEX_BOXES, + TEX_CONES, TEX_TEXTURES, TEX_ENV, TEX_XFORM, @@ -31,6 +34,14 @@ { scn = s; + int max_tex_units; + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_tex_units); + printf("maximum texture units: %d\n", max_tex_units); + if(NUM_SDR_TEXTURES > max_tex_units) { + fprintf(stderr, "not enough texture units available!\n"); + return false; + } + glGenTextures(1, textures + TEX_RAYDIR); glBindTexture(GL_TEXTURE_2D, textures[TEX_RAYDIR]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -46,6 +57,7 @@ textures[TEX_SPHERES] = s->get_texture(GPUScene::TEX_SPHERE); textures[TEX_PLANES] = s->get_texture(GPUScene::TEX_PLANE); textures[TEX_BOXES] = s->get_texture(GPUScene::TEX_BOX); + textures[TEX_CONES] = s->get_texture(GPUScene::TEX_CONE); textures[TEX_TEXTURES] = s->get_texture(GPUScene::TEX_TEXTURE); textures[TEX_ENV] = s->get_texture(GPUScene::TEX_ENV); textures[TEX_XFORM] = s->get_texture(GPUScene::TEX_XFORM); @@ -74,6 +86,7 @@ set_uniform_int(sdr, "tex_spheres", TEX_SPHERES); set_uniform_int(sdr, "tex_planes", TEX_PLANES); set_uniform_int(sdr, "tex_boxes", TEX_BOXES); + set_uniform_int(sdr, "tex_cones", TEX_CONES); set_uniform_int(sdr, "tex_megatex", TEX_TEXTURES); set_uniform_int(sdr, "tex_env", TEX_ENV); set_uniform_int(sdr, "tex_xforms", TEX_XFORM); diff -r 297dbc5080c4 -r 2ed3da7dc0bc src/scene_load.cc --- a/src/scene_load.cc Sun Nov 09 20:13:33 2014 +0200 +++ b/src/scene_load.cc Mon Nov 10 01:26:00 2014 +0200 @@ -5,6 +5,7 @@ #include "sphere.h" #include "plane.h" #include "box.h" +#include "cone.h" #include "light.h" #include "camera.h" #include "texture.h" @@ -13,6 +14,7 @@ static Object *parse_sphere(char **argv, const std::map &materials); static Object *parse_plane(char **argv, const std::map &materials); static Object *parse_box(char **argv, const std::map &materials); +static Object *parse_cone(char **argv, const std::map &materials); static Light *parse_light(char **argv); static Camera *parse_camera(char **argv); static bool parse_env(char **argv, Scene *scn); @@ -77,6 +79,14 @@ } scn->add_object(obj); + } else if(strstr(line, "cone") == line) { + char *args = strip_space(line + strlen("cone")); + Object *obj = parse_cone(split_args(args), materials); + if(!obj) { + goto err; + } + scn->add_object(obj); + } else if(strstr(line, "light") == line) { char *args = strip_space(line + strlen("light")); Light *lt = parse_light(split_args(args)); @@ -153,6 +163,7 @@ const Sphere *sph; const Plane *plane; const Box *box; + const Cone *cone; if((sph = dynamic_cast(obj))) { fprintf(fp, "sphere -material %s", name); fprintf(fp, " -center %.3f %.3f %.3f", sph->pos.x, sph->pos.y, sph->pos.z); @@ -165,6 +176,10 @@ fprintf(fp, "box -material %s", name); fprintf(fp, " -min %.3f %.3f %.3f", box->min.x, box->min.y, box->min.z); fprintf(fp, " -max %.3f %.3f %.3f\n", box->max.x, box->max.y, box->max.z); + } else if((cone = dynamic_cast(obj))) { + fprintf(fp, "cone -material %s", name); + fprintf(fp, " -angle %g", RAD_TO_DEG(cone->angle)); + fprintf(fp, " -start %g -end %g\n", cone->ymin, cone->ymax); } } @@ -374,6 +389,53 @@ return box; } +static Object *parse_cone(char **argv, const std::map &materials) +{ + char *endp; + Cone *cone = new Cone; + + for(int i=0; argv[i]; i++) { + if(strcmp(argv[i], "-name") == 0) { + cone->set_name(argv[++i]); + + } else if(strcmp(argv[i], "-angle") == 0) { + cone->angle = DEG_TO_RAD(strtod(argv[++i], &endp)); + if(endp == argv[i]) { + fprintf(stderr, "failed to parse cone angle\n"); + return 0; + } + + } else if(strcmp(argv[i], "-start") == 0) { + cone->ymin = strtod(argv[++i], &endp); + if(endp == argv[i]) { + fprintf(stderr, "failed to parse cone start\n"); + return 0; + } + + } else if(strcmp(argv[i], "-end") == 0) { + cone->ymax = strtod(argv[++i], &endp); + if(endp == argv[i]) { + fprintf(stderr, "failed to parse cone end\n"); + return 0; + } + + } else if(strcmp(argv[i], "-material") == 0) { + auto it = materials.find(argv[++i]); + if(it == materials.end()) { + fprintf(stderr, "material %s not found\n", argv[i]); + return 0; + } + + cone->material = it->second; + } else { + fprintf(stderr, "invalid box option: %s\n", argv[i]); + return 0; + } + } + + return cone; +} + static Light *parse_light(char **argv) { Light *lt = new Light;