#version 120 #extension GL_NV_geometry_shader4 : enable #extension GL_EXT_gpu_shader4 : enable #define TOPFACE 1000 #define AXIS_X 0 #define AXIS_Y 1 #define AXIS_Z 2 #define TERMINAL 10000 struct BC { vec4 pos, size, rot; }; vec4 currPosition, currSize, currRotation; varying vec4 compPosition, compSize, compRotation, compExtra; float gSizes[5]; float gReplacements[5]; float gRel[5]; float seed; int stackTop = 0; BC stack[5]; float rand(float min, float max) { float linCon = int(16807 * seed) % 65536; seed = linCon; linCon /= 65535; return linCon * (max - min) + min; } void EmitComponent(vec4 pos, vec4 size, vec4 rot) { compPosition = pos; compSize = size; compRotation = rot; compRotation[3] = int(seed + pos[0] + pos[1] + pos[2] + size[0] + size[1] + size[2] + rot[0] + rot[1] + rot[2]) % 65536; EmitVertex(); } void EmitComponent() { compRotation[3] = int(seed + compPosition[0] + compPosition[1] + compPosition[2] + compSize[0] + compSize[1] + compSize[2] + compRotation[0] + compRotation[1] + compRotation[2]) % 65536; EmitVertex(); } void Size(vec3 newSize, vec3 rel, float newId) { compPosition = currPosition; compSize = currSize; compRotation = currRotation; if (rel[0] > 0) { compSize[0] *= newSize[0]; } else { compSize[0] = newSize[0]; } if (rel[1] > 0) { compSize[1] *= newSize[1]; } else { compSize[1] = newSize[1]; } if (rel[2] > 0) { compSize[2] *= newSize[2]; } else { compSize[2] = newSize[2]; } //If a new component with this size should go immediately back in to the list, generate a vertex if (newId != -1) { compPosition[3] = newId; EmitComponent(); } else { currSize = compSize; currPosition = compPosition; currRotation = compRotation; } } void Subdiv(int axis, int numReplacements) { float sumabs = 0; float sumrel = 0; for (int i = 0; i < numReplacements; i++) { if (gRel[i] < 0) sumabs += gSizes[i]; else sumrel += gSizes[i]; } float prev = 0; float val; for (int i = 0; i < numReplacements; i++) { compPosition = currPosition; compSize = currSize; compRotation = currRotation; if (i != 0) { compPosition[axis] = prev; } val = gSizes[i]; if (gRel[i] > 0) { val *= (compSize[axis] - sumabs) / sumrel; } compSize[axis] = val; prev = compPosition[axis] + compSize[axis]; compPosition[3] = gReplacements[i]; if (gReplacements[i] != -1) { EmitComponent(); } } } void Repeat(int axis, float size, float rep) { float nr = ceil(currSize[axis] / size); compRotation = currRotation; //for (int i = 0; i < nr; i++) for (int i = 0; i < 10; i++) { if (i >= nr) break; compPosition = currPosition; compSize = currSize; compPosition[axis] = currPosition[axis] + size * i; if (compPosition[axis] + size > currPosition[axis] + currSize[axis]) { compSize[axis] = currSize[axis] - (size * (nr - 1)); } else { compSize[axis] = size; } compPosition[3] = rep; EmitComponent(); } } void Comp(float rep) { vec4 lp = currPosition, ls = currSize, lr = currRotation; vec4 rp = currPosition, rs = currSize, rr = currRotation; vec4 bp = currPosition, bs = currSize, br = currRotation; vec4 fp = currPosition, fs = currSize, fr = currRotation; vec4 tp = currPosition, ts = currSize, tr = currRotation; fs[2] = 0; fp[2] = currPosition[2] + currSize[2]; fp[3] = rep; EmitComponent(fp, fs, fr); bs[2] = 0; bp[2] = -currPosition[2]; br[1] += 180; bp[0] = -bp[0] - bs[0]; bp[3] = rep; EmitComponent(bp, bs, br); rp[0] = -currPosition[2] - currSize[2]; rs[0] = currSize[2]; rp[2] = currPosition[0] + currSize[0]; rs[2] = 0; rr[1] += 90; rp[3] = rep; EmitComponent(rp, rs, rr); lp[0] = currPosition[2]; ls[0] = currSize[2]; lp[2] = -currPosition[0]; ls[2] = 0; lr[1] += -90; lp[3] = rep; EmitComponent(lp, ls, lr); tr[0] += -90; ts[2] = 0; tp[1] = -currSize[2] - currPosition[2]; ts[1] = currSize[2]; tp[2] = currPosition[1] + currSize[1]; tp[3] = TOPFACE; EmitComponent(tp, ts, tr); } void Texture(int texId) { currPosition[3] = TERMINAL; currSize[3] = texId; EmitComponent(currPosition, currSize, currRotation); } void Replace(int newId) { currPosition[3] = newId; if (newId != -1) { EmitComponent(currPosition, currSize, currRotation); } } void Push() { stack[stackTop].pos = currPosition; stack[stackTop].size = currSize; stack[stackTop].rot = currRotation; stackTop++; } void Pop() { stackTop--; currPosition = stack[stackTop].pos; currSize = stack[stackTop].size; currRotation = stack[stackTop].rot; } void Translate(vec4 trans) { currPosition += trans; } void RotateX(float angle) { currRotation[0] += angle; } void RotateY(float angle) { currRotation[1] += angle; } void RotateZ(float angle) { currRotation[2] += angle; } void main() { currPosition = gl_PositionIn[0]; currSize = gl_FrontColorIn[0]; currRotation = gl_TexCoordIn[0][0]; compExtra = gl_TexCoordIn[0][1]; seed = currRotation[3]; compSize[3] = 0; int id = int(currPosition[3] + 0.5); //This has already been recognized as terminal, so go ahead and prevent from having to do other checks if (id == TERMINAL) { compPosition = currPosition; compSize = currSize; compRotation = currRotation; EmitComponent(); return; } <> //Nothing applied, this is a permanent component. compPosition = currPosition; compSize = currSize; compRotation = currRotation; compPosition[3] = TERMINAL; EmitComponent(); }