paysages3d/src/render/opengl/OpenGLVegetationImpostor.cpp

107 lines
3.9 KiB
C++
Raw Normal View History

#include "OpenGLVegetationImpostor.h"
#include "OpenGLShaderProgram.h"
#include "OpenGLSharedState.h"
#include "OpenGLVegetationInstance.h"
#include "Texture2D.h"
#include "SoftwareRenderer.h"
#include "Scenery.h"
#include "AtmosphereDefinition.h"
#include "GodRaysSampler.h"
#include "VegetationRenderer.h"
#include "VegetationInstance.h"
#include "RayCastingResult.h"
#include "SpaceSegment.h"
#include "Matrix4.h"
#include "LightingManager.h"
#include "CameraDefinition.h"
OpenGLVegetationImpostor::OpenGLVegetationImpostor(int partsize) {
vertices = new float[4 * 3];
texture_size = partsize * 4;
texture = new Texture2D(texture_size, texture_size);
texture_changed = true;
setVertex(0, 0.0f, 0.0f, 0.0f);
setVertex(1, 0.0f, 0.0f, 1.0f);
setVertex(2, 0.0f, 1.0f, 0.0f);
setVertex(3, 0.0f, 1.0f, 1.0f);
}
OpenGLVegetationImpostor::~OpenGLVegetationImpostor() {
delete[] vertices;
delete texture;
}
void OpenGLVegetationImpostor::render(OpenGLShaderProgram *program, const OpenGLVegetationInstance *instance,
int index) {
if (index == 0 or texture_changed) {
texture_changed = false;
program->getState()->set("impostorTexture", texture);
}
program->getState()->setInt("index", 15); // TODO
program->getState()->set("offset", instance->getBase());
program->getState()->set("size", instance->getSize());
program->drawTriangleStrip(vertices, 4);
}
void OpenGLVegetationImpostor::prepareTexture(const VegetationModelDefinition &model, const Scenery &environment,
bool *interrupt) {
Scenery scenery;
environment.getAtmosphere()->copy(scenery.getAtmosphere());
SoftwareRenderer renderer(&scenery);
// FIXME Self light filtering
renderer.getLightingManager()->clearFilters();
renderer.getGodRaysSampler()->setEnabled(false);
VegetationRenderer *vegetation = renderer.getVegetationRenderer();
VegetationInstance instance(model, VECTOR_ZERO);
int parts = 4;
int partsize = texture_size / parts;
Matrix4 rotation;
for (int py = 0; py < parts; py++) {
for (int px = 0; px < parts; px++) {
int index = py * parts + px;
if (index == 0) {
rotation = Matrix4::newRotateX(-M_PI_2);
} else if (index < 6) {
rotation = Matrix4::newRotateY(M_2PI * (double)(index - 1) * 0.2).mult(Matrix4::newRotateX(-M_PI_4));
} else {
rotation = Matrix4::newRotateY(M_2PI * (double)(index - 6) * 0.1);
}
Vector3 cam(0.0, 0.0, 5.0);
scenery.getCamera()->setLocation(rotation.multPoint(cam));
scenery.getCamera()->setTarget(VECTOR_ZERO);
renderer.prepare();
int startx = px * partsize;
int starty = py * partsize;
for (int x = 0; x < partsize; x++) {
double dx = (double)x / (double)partsize;
for (int y = 0; y < partsize; y++) {
double dy = (double)y / (double)partsize;
Vector3 near(dx - 0.5, dy - 0.5, 5.0);
Vector3 far(dx - 0.5, dy - 0.5, -5.0);
SpaceSegment segment(rotation.multPoint(near.scale(1.3)).add(VECTOR_UP.scale(0.5)),
rotation.multPoint(far.scale(1.3)).add(VECTOR_UP.scale(0.5)));
RayCastingResult result = vegetation->renderInstance(segment, instance, false, true);
texture->setPixel(startx + x, starty + y,
result.hit ? result.hit_color.normalized() : COLOR_TRANSPARENT);
}
}
}
}
texture_changed = true;
}
void OpenGLVegetationImpostor::setVertex(int i, float x, float y, float z) {
vertices[i * 3] = x;
vertices[i * 3 + 1] = y;
vertices[i * 3 + 2] = z;
}