bloboland

changeset 4:9021a906c5d3

lots of stuff
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 18 Dec 2012 06:13:09 +0200
parents a39c301cdcce
children 2f4406cc341e
files sdr/bloboray.p.glsl src/game.cc src/level.cc src/level.h src/main.cc src/opt.cc src/opt.h src/renderer.cc src/renderer.h src/texture.cc src/texture.h
diffstat 11 files changed, 329 insertions(+), 30 deletions(-) [+]
line diff
     1.1 --- a/sdr/bloboray.p.glsl	Sun Dec 16 14:24:16 2012 +0200
     1.2 +++ b/sdr/bloboray.p.glsl	Tue Dec 18 06:13:09 2012 +0200
     1.3 @@ -12,32 +12,60 @@
     1.4  	float t0, t1;
     1.5  	vec3 pos, normal;
     1.6  	vec4 color;
     1.7 +	vec3 refl;
     1.8  };
     1.9  
    1.10  vec3 shade(Ray ray, HitPoint hit);
    1.11 -HitPoint intersect_voxels(Ray ray);
    1.12 +vec3 sky(Ray ray);
    1.13 +HitPoint ray_march(Ray ray);
    1.14 +float eval_blobs(vec3 pt);
    1.15 +vec3 calc_blob_normal(vec3 pt);
    1.16  HitPoint intersect_aabb(Ray ray, AABBox aabb);
    1.17  Ray get_primary_ray(float x, float y);
    1.18 +float luminance(vec3 col);
    1.19 +float fresnel(float r, float cosa);
    1.20 +vec3 get_blob(int i);
    1.21  
    1.22 -#define RAY_STEP	0.001
    1.23 +#define BLOB_THRESHOLD	0.5
    1.24 +#define BLOB_SCALE		(1.0 / 4.0)
    1.25 +#define MAX_ITER		1
    1.26 +
    1.27 +#define RAY_STEP	(0.75 / volsize.z)
    1.28  
    1.29  #define FOV		camprop.x
    1.30  #define ASPECT	camprop.y
    1.31  uniform vec4 camprop;
    1.32  uniform vec3 volsize;
    1.33  uniform sampler3D voltex;
    1.34 +uniform vec3 worldsize;
    1.35  
    1.36 -//const vec3 worldsize = vec3(4.0, 4.0, 2.0);
    1.37 -const vec3 worldsize = vec3(1.0, 1.0, 0.5);
    1.38 +uniform sampler1D blobtex;
    1.39 +uniform int num_blobs;
    1.40  
    1.41  void main()
    1.42  {
    1.43  	Ray ray = get_primary_ray(gl_TexCoord[0].x, gl_TexCoord[0].y);
    1.44  
    1.45 +	HitPoint hit;
    1.46  	vec3 color = vec3(0.0, 0.0, 0.0);
    1.47 -	HitPoint hit = intersect_voxels(ray);
    1.48 -	if(hit.hit) {
    1.49 -		color = shade(ray, hit);
    1.50 +	vec3 power = vec3(1.0, 1.0, 1.0);
    1.51 +
    1.52 +	for(int i=0; i<=MAX_ITER; i++) {
    1.53 +		hit = ray_march(ray);
    1.54 +		if(hit.hit) {
    1.55 +			color += shade(ray, hit) * power;
    1.56 +		} else {
    1.57 +			color += sky(ray) * power;
    1.58 +			break;
    1.59 +		}
    1.60 +
    1.61 +		ray.origin = hit.pos + hit.normal * RAY_STEP;
    1.62 +		ray.dir = reflect(ray.dir, hit.normal);
    1.63 +		power *= hit.refl;
    1.64 +
    1.65 +		if(luminance(power) < 0.075) {
    1.66 +			break;
    1.67 +		}
    1.68  	}
    1.69  
    1.70  	gl_FragColor = vec4(color, 1.0);
    1.71 @@ -55,9 +83,30 @@
    1.72  	float ndoth = max(dot(hit.normal, hvec), 0.0);
    1.73  
    1.74  	vec3 diffuse = hit.color.xyz * ndotl;
    1.75 -	vec3 specular = vec3(0.4, 0.4, 0.4) * pow(ndoth, 60.0);
    1.76 +	vec3 specular = hit.refl * pow(ndoth, 60.0);
    1.77  
    1.78 -	return diffuse + specular;
    1.79 +	vec3 color = diffuse + specular;
    1.80 +
    1.81 +	float fog = 0.0;//smoothstep(4.0, 8.0, hit.t0);
    1.82 +
    1.83 +	//const float fog_density = 0.18;
    1.84 +	//float fog = exp(-fog_density * fog_density * hit.t0 * hit.t0);
    1.85 +	//fog = clamp(fog, 0.0, 1.0);
    1.86 +
    1.87 +	return mix(color, sky(ray), fog);
    1.88 +}
    1.89 +
    1.90 +#define M_PI	3.141592653
    1.91 +
    1.92 +vec3 sky(Ray ray)
    1.93 +{
    1.94 +	const vec3 horiz = vec3(0.64, 0.70, 0.76);
    1.95 +	const vec3 zenith = vec3(0.65, 0.82, 0.94);
    1.96 +
    1.97 +	float angle = acos(ray.dir.y);
    1.98 +	float t = 1.0 - angle / (M_PI / 2.0);
    1.99 +
   1.100 +	return mix(horiz, zenith, smoothstep(-0.2, 0.2, t));
   1.101  }
   1.102  
   1.103  vec4 fetch_voxel(vec3 pt)
   1.104 @@ -68,7 +117,7 @@
   1.105  
   1.106  vec3 calc_voxel_normal(vec3 pt)
   1.107  {
   1.108 -	vec3 offs = 1.8 / volsize;
   1.109 +	vec3 offs = 6.0 / volsize;
   1.110  	float dfdx = fetch_voxel(pt + vec3(offs.x, 0.0, 0.0)).w - fetch_voxel(pt - vec3(offs.x, 0.0, 0.0)).w;
   1.111  	float dfdy = fetch_voxel(pt + vec3(0.0, offs.y, 0.0)).w - fetch_voxel(pt - vec3(0.0, offs.y, 0.0)).w;
   1.112  	float dfdz = fetch_voxel(pt + vec3(0.0, 0.0, offs.z)).w - fetch_voxel(pt - vec3(0.0, 0.0, offs.z)).w;
   1.113 @@ -76,12 +125,17 @@
   1.114  	return -normalize(vec3(dfdx, dfdy, dfdz));
   1.115  }
   1.116  
   1.117 -HitPoint intersect_voxels(Ray ray)
   1.118 +HitPoint ray_march(Ray ray)
   1.119  {
   1.120  	HitPoint hit;
   1.121  	//AABBox aabb = AABBox(vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0));
   1.122  	AABBox aabb = AABBox(-worldsize.xzy, worldsize.xzy);
   1.123  
   1.124 +	hit.hit = false;
   1.125 +	hit.t0 = hit.t1 = 0.0;
   1.126 +	hit.pos = hit.normal = vec3(0.0, 0.0, 0.0);
   1.127 +	hit.color = vec4(1.0, 1.0, 1.0, 1.0);
   1.128 +
   1.129  
   1.130  	hit = intersect_aabb(ray, aabb);
   1.131  	if(!hit.hit) {
   1.132 @@ -96,14 +150,25 @@
   1.133  
   1.134  	while(dist < end_dist) {
   1.135  		vec3 pt = ray.origin + ray.dir * dist;
   1.136 +
   1.137 +		// first try evaluating the blob field at this point
   1.138 +		float blob = eval_blobs(pt);
   1.139 +		if(blob >= BLOB_THRESHOLD) {
   1.140 +			hit.t0 = dist;
   1.141 +			hit.pos = pt;
   1.142 +			hit.normal = calc_blob_normal(pt);
   1.143 +			hit.color = vec4(0.0, 0.0, 0.0, 1.0);
   1.144 +			hit.refl = vec3(1.0, 0.9, 0.75);
   1.145 +			return hit;
   1.146 +		}
   1.147 +
   1.148  		vec4 voxel = fetch_voxel(pt.xzy);
   1.149 -
   1.150 -
   1.151  		if(voxel.a > 0.5) {
   1.152  			hit.t0 = dist;
   1.153  			hit.pos = pt;
   1.154  			hit.normal = calc_voxel_normal(pt.xzy).xzy;
   1.155  			hit.color = voxel;
   1.156 +			hit.refl = vec3(0.0, 0.0, 0.0);
   1.157  			return hit;
   1.158  		}
   1.159  
   1.160 @@ -114,24 +179,48 @@
   1.161  	return hit;
   1.162  }
   1.163  
   1.164 +float eval_blobs(vec3 pt)
   1.165 +{
   1.166 +	float val = 0.0;
   1.167 +
   1.168 +	for(int i=0; i<num_blobs; i++) {
   1.169 +		float dist = length(pt - get_blob(i));
   1.170 +		val += (dist * dist * (3.0 - 2.0 * dist));
   1.171 +	}
   1.172 +	return val;
   1.173 +}
   1.174 +
   1.175 +vec3 calc_blob_normal(vec3 pt)
   1.176 +{
   1.177 +	const float offs = 0.01;
   1.178 +	vec3 grad;
   1.179 +	grad.x = eval_blobs(pt + vec3(offs, 0.0, 0.0)) - eval_blobs(pt - vec3(offs, 0.0, 0.0));
   1.180 +	grad.y = eval_blobs(pt + vec3(0.0, offs, 0.0)) - eval_blobs(pt - vec3(0.0, offs, 0.0));
   1.181 +	grad.z = eval_blobs(pt + vec3(0.0, 0.0, offs)) - eval_blobs(pt - vec3(0.0, 0.0, offs));
   1.182 +
   1.183 +	return -normalize(grad);
   1.184 +}
   1.185 +
   1.186  HitPoint intersect_aabb(Ray ray, AABBox aabb)
   1.187  {
   1.188  	HitPoint res;
   1.189  
   1.190 +	res.pos = res.normal = vec3(0.0, 0.0, 0.0);
   1.191 +	res.color = vec4(1.0, 1.0, 1.0, 1.0);
   1.192 +	res.refl = vec3(0.0, 0.0, 0.0);
   1.193 +
   1.194  	vec3 invR = 1.0 / ray.dir;
   1.195 -    vec3 tbot = invR * (aabb.vmin - ray.origin);
   1.196 -    vec3 ttop = invR * (aabb.vmax - ray.origin);
   1.197 -    vec3 tmin = min(ttop, tbot);
   1.198 -    vec3 tmax = max(ttop, tbot);
   1.199 -    vec2 t = max(tmin.xx, tmin.yz);
   1.200 -    float t0 = max(t.x, t.y);
   1.201 -    t = min(tmax.xx, tmax.yz);
   1.202 -    float t1 = min(t.x, t.y);
   1.203 +	vec3 tbot = invR * (aabb.vmin - ray.origin);
   1.204 +	vec3 ttop = invR * (aabb.vmax - ray.origin);
   1.205 +	vec3 tmin = min(ttop, tbot);
   1.206 +	vec3 tmax = max(ttop, tbot);
   1.207 +	vec2 t = max(tmin.xx, tmin.yz);
   1.208 +	res.t0 = max(t.x, t.y);
   1.209 +	t = min(tmax.xx, tmax.yz);
   1.210 +	res.t1 = min(t.x, t.y);
   1.211  
   1.212 -	if(t0 <= t1) {
   1.213 +	if(res.t0 <= res.t1) {
   1.214  		res.hit = true;
   1.215 -		res.t0 = t0;
   1.216 -		res.t1 = t1;
   1.217  	} else {
   1.218  		res.hit = false;
   1.219  	}
   1.220 @@ -150,3 +239,24 @@
   1.221  	ray.dir = gl_NormalMatrix * normalize(dir);
   1.222  	return ray;
   1.223  }
   1.224 +
   1.225 +float luminance(vec3 col)
   1.226 +{
   1.227 +	//const vec3 fact = vec3(0.2126, 0.7152, 0.0722);
   1.228 +	//return dot(col, fact);
   1.229 +	return (col.x + col.y + col.z) / 3.0;
   1.230 +}
   1.231 +
   1.232 +float fresnel(float r, float cosa)
   1.233 +{
   1.234 +	float inv_cosa = 1.0 - cosa;
   1.235 +	float inv_cosa_sq = inv_cosa * inv_cosa;
   1.236 +
   1.237 +	return r + (1.0 - r) * inv_cosa_sq * inv_cosa_sq * inv_cosa;
   1.238 +}
   1.239 +
   1.240 +vec3 get_blob(int i)
   1.241 +{
   1.242 +	float tc = float(i) / float(num_blobs);
   1.243 +	return texture1D(blobtex, tc).xyz;
   1.244 +}
     2.1 --- a/src/game.cc	Sun Dec 16 14:24:16 2012 +0200
     2.2 +++ b/src/game.cc	Tue Dec 18 06:13:09 2012 +0200
     2.3 @@ -20,6 +20,9 @@
     2.4  static Renderer *rend;
     2.5  static FpsCamera cam;
     2.6  
     2.7 +static const float fog_color[] = {0.76, 0.64, 0.91, 1.0};
     2.8 +static Vector3 gravity;
     2.9 +
    2.10  bool game_init()
    2.11  {
    2.12  	printf("initializing OpenGL state\n");
    2.13 @@ -33,6 +36,7 @@
    2.14  
    2.15  	printf("generating level\n");
    2.16  	level = new Level;
    2.17 +	level->world_size = Vector3(8, 8, 4);
    2.18  	level->generate();
    2.19  
    2.20  	printf("initializing renderer\n");
    2.21 @@ -44,6 +48,11 @@
    2.22  	cam.input_move(0, 2, 2);
    2.23  	cam.input_rotate(0, M_PI / 5, 0);
    2.24  
    2.25 +	glClearColor(fog_color[0], fog_color[1], fog_color[2], 1.0);
    2.26 +	glFogfv(GL_FOG_COLOR, fog_color);
    2.27 +
    2.28 +	gravity = Vector3(0, -0.01, 0);
    2.29 +
    2.30  	return true;
    2.31  }
    2.32  
    2.33 @@ -73,6 +82,18 @@
    2.34  	}
    2.35  
    2.36  	cam.input_move(dx, 0, dy);
    2.37 +
    2.38 +	for(size_t i=0; i<level->blobs.size(); i++) {
    2.39 +		Blob *b = &level->blobs[i];
    2.40 +
    2.41 +		b->velocity += gravity * dt;
    2.42 +		Vector3 npos = b->pos + b->velocity * dt;
    2.43 +
    2.44 +		Vector3 normal;
    2.45 +		if(level->collision(b->pos, npos, &npos, &normal)) {
    2.46 +			b->velocity = b->velocity.reflection(normal);
    2.47 +		}
    2.48 +	}
    2.49  }
    2.50  
    2.51  void game_render()
    2.52 @@ -81,6 +102,7 @@
    2.53  
    2.54  	if(opt.stereo) {
    2.55  		glDrawBuffer(GL_BACK_LEFT);
    2.56 +		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    2.57  
    2.58  		glMatrixMode(GL_PROJECTION);
    2.59  		glLoadIdentity();
    2.60 @@ -92,6 +114,7 @@
    2.61  		rend->render();
    2.62  
    2.63  		glDrawBuffer(GL_BACK_RIGHT);
    2.64 +		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    2.65  
    2.66  		glMatrixMode(GL_PROJECTION);
    2.67  		glLoadIdentity();
    2.68 @@ -102,6 +125,8 @@
    2.69  
    2.70  		rend->render();
    2.71  	} else {
    2.72 +		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    2.73 +
    2.74  		glMatrixMode(GL_PROJECTION);
    2.75  		glLoadIdentity();
    2.76  		proj_matrix(0);
     3.1 --- a/src/level.cc	Sun Dec 16 14:24:16 2012 +0200
     3.2 +++ b/src/level.cc	Tue Dec 18 06:13:09 2012 +0200
     3.3 @@ -5,6 +5,7 @@
     3.4  Level::Level()
     3.5  {
     3.6  	terrain = 0;
     3.7 +	world_size = Vector3(1, 1, 1);
     3.8  }
     3.9  
    3.10  Level::~Level()
    3.11 @@ -19,7 +20,7 @@
    3.12  	float valley = nx * nx + ny * ny;
    3.13  
    3.14  	float s = opt.gen_noise_scale;
    3.15 -	float noise = 0.2 * fbm2(x * s, y * s, 3) * (valley + 0.25);
    3.16 +	float noise = 0.2 * fbm2(x * s, y * s, 4) * (valley + 0.25);
    3.17  	float grad = 0.75 - z + noise + valley * 0.4;
    3.18  
    3.19  	return grad;
    3.20 @@ -56,7 +57,7 @@
    3.21  				} else if(z < 0.8) {
    3.22  					if(alpha < 0.56) {
    3.23  						// grass
    3.24 -						voxel = Vector4(0.68, 0.95, 0.38);
    3.25 +						voxel = Vector4(0.49, 0.72, 0.48);
    3.26  					} else {
    3.27  						// mud
    3.28  						voxel = Vector4(0.57, 0.43, 0.29, 1);
    3.29 @@ -68,6 +69,14 @@
    3.30  			}
    3.31  		}
    3.32  	}
    3.33 +
    3.34 +	// generate some blobs
    3.35 +	for(int i=0; i<opt.gen_num_blobs; i++) {
    3.36 +		Blob b;
    3.37 +		b.pos = Vector3(frand(1.0) - 0.5, 10.0, frand(1.0) - 0.5);
    3.38 +		b.velocity = Vector3(0, 0, 0);
    3.39 +		blobs.push_back(b);
    3.40 +	}
    3.41  }
    3.42  
    3.43  bool Level::load(const char *fname)
    3.44 @@ -79,3 +88,50 @@
    3.45  {
    3.46  	return false;
    3.47  }
    3.48 +
    3.49 +#define CLAMP(x, a, b)	((x) < (a) ? (a) : ((x) > (b) ? (b) : (x)))
    3.50 +
    3.51 +const Vector4 &Level::get_voxel(const Vector3 &pos) const
    3.52 +{
    3.53 +	Vector3 p = pos / world_size + Vector3(0.5, 0.5, 0.5);
    3.54 +
    3.55 +	int xsz = terrain->get_size(0);
    3.56 +	int ysz = terrain->get_size(1);
    3.57 +	int zsz = terrain->get_size(2);
    3.58 +
    3.59 +	int i = (int)(p.x * xsz);
    3.60 +	int j = (int)(p.y * ysz);
    3.61 +	int k = (int)(p.z * zsz);
    3.62 +
    3.63 +	return terrain->get_voxel(CLAMP(i, 0, xsz - 1), CLAMP(j, 0, ysz - 1), CLAMP(k, 0, zsz - 1));
    3.64 +}
    3.65 +
    3.66 +Vector3 Level::calc_normal(const Vector3 &pos) const
    3.67 +{
    3.68 +	int xsz = terrain->get_size(0);
    3.69 +	int ysz = terrain->get_size(1);
    3.70 +	int zsz = terrain->get_size(2);
    3.71 +
    3.72 +	float dx = world_size.x / (float)xsz;
    3.73 +	float dy = world_size.y / (float)ysz;
    3.74 +	float dz = world_size.z / (float)zsz;
    3.75 +
    3.76 +	float dfdx = get_voxel(pos + Vector3(dx, 0, 0)).w - get_voxel(pos - Vector3(dx, 0, 0)).w;
    3.77 +	float dfdy = get_voxel(pos + Vector3(0, dy, 0)).w - get_voxel(pos - Vector3(0, dy, 0)).w;
    3.78 +	float dfdz = get_voxel(pos + Vector3(0, 0, dz)).w - get_voxel(pos - Vector3(0, 0, dz)).w;
    3.79 +
    3.80 +	return Vector3(dfdx, dfdy, dfdz);
    3.81 +}
    3.82 +
    3.83 +bool Level::collision(const Vector3 &pos0, const Vector3 &pos1, Vector3 *outpos, Vector3 *outnorm) const
    3.84 +{
    3.85 +	Vector4 vox0 = get_voxel(pos0);
    3.86 +	Vector4 vox1 = get_voxel(pos1);
    3.87 +
    3.88 +	if(vox0.w < 0.5 && vox1.w >= 0.5) {
    3.89 +		*outpos = lerp(pos0, pos1, 0.5);	// TODO
    3.90 +		*outnorm = calc_normal(*outpos);
    3.91 +		return true;
    3.92 +	}
    3.93 +	return false;
    3.94 +}
     4.1 --- a/src/level.h	Sun Dec 16 14:24:16 2012 +0200
     4.2 +++ b/src/level.h	Tue Dec 18 06:13:09 2012 +0200
     4.3 @@ -4,10 +4,17 @@
     4.4  #include <vector>
     4.5  #include "volume.h"
     4.6  
     4.7 +struct Blob {
     4.8 +	Vector3 pos;
     4.9 +	Vector3 velocity;
    4.10 +};
    4.11 +
    4.12  class Level {
    4.13  public:
    4.14  	Volume *terrain;
    4.15 -	std::vector<Vector3> blobs;
    4.16 +	std::vector<Blob> blobs;
    4.17 +
    4.18 +	Vector3 world_size;
    4.19  
    4.20  	Level();
    4.21  	~Level();
    4.22 @@ -16,6 +23,11 @@
    4.23  
    4.24  	bool load(const char *fname);
    4.25  	bool save(const char *fname) const;
    4.26 +
    4.27 +	const Vector4 &get_voxel(const Vector3 &pos) const;
    4.28 +	Vector3 calc_normal(const Vector3 &pos) const;
    4.29 +
    4.30 +	bool collision(const Vector3 &pos0, const Vector3 &pos1, Vector3 *outpos, Vector3 *outnorm) const;
    4.31  };
    4.32  
    4.33  #endif	// LEVEL_H_
     5.1 --- a/src/main.cc	Sun Dec 16 14:24:16 2012 +0200
     5.2 +++ b/src/main.cc	Tue Dec 18 06:13:09 2012 +0200
     5.3 @@ -63,7 +63,6 @@
     5.4  	game_iter((msec - prev_msec) / 1000.0);
     5.5  	prev_msec = msec;
     5.6  
     5.7 -
     5.8  	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     5.9  
    5.10  	game_render();
     6.1 --- a/src/opt.cc	Sun Dec 16 14:24:16 2012 +0200
     6.2 +++ b/src/opt.cc	Tue Dec 18 06:13:09 2012 +0200
     6.3 @@ -15,6 +15,7 @@
     6.4  	opt.world_size[2] = 64;
     6.5  
     6.6  	opt.gen_noise_scale = 1.0f;
     6.7 +	opt.gen_num_blobs = 10;
     6.8  }
     6.9  
    6.10  bool parse_opt(int argc, char **argv)
    6.11 @@ -40,6 +41,13 @@
    6.12  					fprintf(stderr, "-genscale must be followed by a scaling factor\n");
    6.13  					return false;
    6.14  				}
    6.15 +			} else if(strcmp(argv[i], "-blobs") == 0) {
    6.16 +				char *endp;
    6.17 +				opt.gen_num_blobs = strtol(argv[++i], &endp, 10);
    6.18 +				if(endp == argv[i]) {
    6.19 +					fprintf(stderr, "-blobs must be followed by the number of blobs\n");
    6.20 +					return false;
    6.21 +				}
    6.22  			} else if(strcmp(argv[i], "-stereo") == 0) {
    6.23  				opt.stereo = true;
    6.24  			} else {
     7.1 --- a/src/opt.h	Sun Dec 16 14:24:16 2012 +0200
     7.2 +++ b/src/opt.h	Tue Dec 18 06:13:09 2012 +0200
     7.3 @@ -8,6 +8,7 @@
     7.4  	// initial parameters when generating new worlds
     7.5  	int world_size[3];
     7.6  	float gen_noise_scale;
     7.7 +	int gen_num_blobs;
     7.8  };
     7.9  
    7.10  extern Options opt;
     8.1 --- a/src/renderer.cc	Sun Dec 16 14:24:16 2012 +0200
     8.2 +++ b/src/renderer.cc	Tue Dec 18 06:13:09 2012 +0200
     8.3 @@ -4,6 +4,7 @@
     8.4  
     8.5  Renderer::Renderer()
     8.6  {
     8.7 +	blobtex = 0;
     8.8  	leveltex = 0;
     8.9  	sdrprog = 0;
    8.10  
    8.11 @@ -29,6 +30,10 @@
    8.12  	leveltex = new Texture3D;
    8.13  	leveltex->create(vol->get_size(0), vol->get_size(1), vol->get_size(2));
    8.14  
    8.15 +	blobtex = new Texture1D;
    8.16 +	blobtex->create(level->blobs.size());
    8.17 +	blobtex->set_filtering(GL_NEAREST);
    8.18 +
    8.19  	this->level = level;
    8.20  
    8.21  	return true;
    8.22 @@ -57,11 +62,19 @@
    8.23  void Renderer::render() const
    8.24  {
    8.25  	leveltex->update((float*)level->terrain->get_data_ptr());
    8.26 -	bind_texture(leveltex);
    8.27 +	((Renderer*)this)->update_blobtex();
    8.28  
    8.29 +	bind_texture(leveltex, 0);
    8.30 +	bind_texture(blobtex, 1);
    8.31 +
    8.32 +	set_uniform_float3(sdrprog, "worldsize", level->world_size.x, level->world_size.y,
    8.33 +			level->world_size.z);
    8.34  	set_uniform_float3(sdrprog, "volsize", level->terrain->get_size(0),
    8.35  			level->terrain->get_size(1), level->terrain->get_size(2));
    8.36  	set_uniform_float4(sdrprog, "camprop", fov, aspect, 0, 0);
    8.37 +
    8.38 +	set_uniform_int(sdrprog, "voltex", 0);
    8.39 +	set_uniform_int(sdrprog, "blobtex", 1);
    8.40  	bind_program(sdrprog);
    8.41  
    8.42  	glBegin(GL_QUADS);
    8.43 @@ -76,7 +89,8 @@
    8.44  	glEnd();
    8.45  
    8.46  	bind_program(0);
    8.47 -	bind_texture(0);
    8.48 +	bind_texture(0, 1);
    8.49 +	bind_texture(0, 0);
    8.50  
    8.51  	/*glEnable(GL_COLOR_MATERIAL);
    8.52  	glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
    8.53 @@ -147,3 +161,20 @@
    8.54  	glVertex3f(pos.x - sz, pos.y - sz, pos.z + sz);
    8.55  
    8.56  }
    8.57 +
    8.58 +void Renderer::update_blobtex()
    8.59 +{
    8.60 +	int nblobs = (int)level->blobs.size();
    8.61 +
    8.62 +	float *data = (float*)alloca(nblobs * 4 * sizeof *data);
    8.63 +	float *dptr = data;
    8.64 +
    8.65 +	for(int i=0; i<nblobs; i++) {
    8.66 +		*dptr++ = level->blobs[i].pos.x;
    8.67 +		*dptr++ = level->blobs[i].pos.y;
    8.68 +		*dptr++ = level->blobs[i].pos.z;
    8.69 +		*dptr++ = 1.0;
    8.70 +	}
    8.71 +
    8.72 +	blobtex->update(data);
    8.73 +}
     9.1 --- a/src/renderer.h	Sun Dec 16 14:24:16 2012 +0200
     9.2 +++ b/src/renderer.h	Tue Dec 18 06:13:09 2012 +0200
     9.3 @@ -7,11 +7,14 @@
     9.4  class Renderer {
     9.5  private:
     9.6  	Level *level;
     9.7 +	Texture1D *blobtex;
     9.8  	Texture3D *leveltex;
     9.9  	unsigned int sdrprog;
    9.10  
    9.11  	float fov, aspect;
    9.12  
    9.13 +	void update_blobtex();
    9.14 +
    9.15  public:
    9.16  	Renderer();
    9.17  	~Renderer();
    10.1 --- a/src/texture.cc	Sun Dec 16 14:24:16 2012 +0200
    10.2 +++ b/src/texture.cc	Tue Dec 18 06:13:09 2012 +0200
    10.3 @@ -38,11 +38,53 @@
    10.4  	}
    10.5  }
    10.6  
    10.7 +void Texture::set_filtering(unsigned int min_filter, unsigned int mag_filter)
    10.8 +{
    10.9 +	if(mag_filter == 0) {
   10.10 +		mag_filter = min_filter;
   10.11 +	}
   10.12 +
   10.13 +	glBindTexture(type, tex);
   10.14 +	glTexParameteri(type, GL_TEXTURE_MIN_FILTER, min_filter);
   10.15 +	glTexParameteri(type, GL_TEXTURE_MAG_FILTER, mag_filter);
   10.16 +}
   10.17 +
   10.18 +void Texture::set_wrapping(unsigned int wrap)
   10.19 +{
   10.20 +	glBindTexture(type, tex);
   10.21 +	glTexParameteri(type, GL_TEXTURE_WRAP_S, wrap);
   10.22 +	glTexParameteri(type, GL_TEXTURE_WRAP_T, wrap);
   10.23 +	glTexParameteri(type, GL_TEXTURE_WRAP_R, wrap);
   10.24 +}
   10.25 +
   10.26  int Texture::get_size(int idx) const
   10.27  {
   10.28  	return idx >= 0 && idx < 3 ? size[idx] : 0;
   10.29  }
   10.30  
   10.31 +Texture1D::Texture1D()
   10.32 +{
   10.33 +	type = GL_TEXTURE_1D;
   10.34 +
   10.35 +	glBindTexture(type, tex);
   10.36 +	glTexParameteri(type, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   10.37 +	glTexParameteri(type, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   10.38 +}
   10.39 +
   10.40 +void Texture1D::create(int sz, float *data)
   10.41 +{
   10.42 +	glBindTexture(type, tex);
   10.43 +	glTexImage1D(type, 0, GL_RGBA, sz, 0, GL_RGBA, GL_FLOAT, data);
   10.44 +
   10.45 +	size[0] = sz;
   10.46 +}
   10.47 +
   10.48 +void Texture1D::update(float *data)
   10.49 +{
   10.50 +	glBindTexture(type, tex);
   10.51 +	glTexSubImage1D(type, 0, 0, size[0], GL_RGBA, GL_FLOAT, data);
   10.52 +}
   10.53 +
   10.54  Texture2D::Texture2D()
   10.55  {
   10.56  	type = GL_TEXTURE_2D;
    11.1 --- a/src/texture.h	Sun Dec 16 14:24:16 2012 +0200
    11.2 +++ b/src/texture.h	Tue Dec 18 06:13:09 2012 +0200
    11.3 @@ -12,6 +12,9 @@
    11.4  	Texture();
    11.5  	virtual ~Texture();
    11.6  
    11.7 +	virtual void set_filtering(unsigned int min_filter, unsigned int mag_filter = 0);
    11.8 +	virtual void set_wrapping(unsigned int wrap);
    11.9 +
   11.10  	virtual int get_size(int idx) const;
   11.11  
   11.12  	virtual void update(float *data) = 0;
   11.13 @@ -21,6 +24,15 @@
   11.14  
   11.15  void bind_texture(const Texture *tex, int texunit = 0);
   11.16  
   11.17 +class Texture1D : public Texture {
   11.18 +public:
   11.19 +	Texture1D();
   11.20 +
   11.21 +	void create(int sz, float *data = 0);
   11.22 +
   11.23 +	void update(float *data);
   11.24 +};
   11.25 +
   11.26  class Texture2D : public Texture {
   11.27  public:
   11.28  	Texture2D();