mirror of
https://github.com/rwengine/openrw.git
synced 2024-11-22 10:22:52 +01:00
Primitive water rendering
This commit is contained in:
parent
ad6eda9024
commit
208a2a9897
@ -229,10 +229,22 @@ public:
|
|||||||
*/
|
*/
|
||||||
std::map<std::string, std::shared_ptr<DynamicObjectData>> dynamicObjectData;
|
std::map<std::string, std::shared_ptr<DynamicObjectData>> dynamicObjectData;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Water Rectangles
|
* @struct WaterArea
|
||||||
|
* Stores Water Rectangle Information
|
||||||
*/
|
*/
|
||||||
std::vector<RWTypes::WaterRect> waterRects;
|
struct WaterArea
|
||||||
|
{
|
||||||
|
float height;
|
||||||
|
float xLeft, yBottom;
|
||||||
|
float xRight, yTop;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Water Areas
|
||||||
|
*/
|
||||||
|
std::vector<WaterArea> waterBlocks;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Water heights
|
* Water heights
|
||||||
|
@ -46,16 +46,6 @@ struct RGBA
|
|||||||
uint8_t r, g, b, a;
|
uint8_t r, g, b, a;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @struct WaterRect
|
|
||||||
* Rectangle with water information
|
|
||||||
*/
|
|
||||||
struct WaterRect
|
|
||||||
{
|
|
||||||
float height;
|
|
||||||
float xLeft, yBottom;
|
|
||||||
float xRight, yTop;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -59,12 +59,13 @@ public:
|
|||||||
GLint uniMatDiffuse, uniMatAmbient, uniFogStart, uniFogEnd;
|
GLint uniMatDiffuse, uniMatAmbient, uniFogStart, uniFogEnd;
|
||||||
GLuint worldProgram;
|
GLuint worldProgram;
|
||||||
GLuint skyProgram;
|
GLuint skyProgram;
|
||||||
|
GLuint waterProgram, waterMVP, waterHeight, waterTexture, waterSize;
|
||||||
GLint skyUniView, skyUniProj, skyUniTop, skyUniBottom;
|
GLint skyUniView, skyUniProj, skyUniTop, skyUniBottom;
|
||||||
|
|
||||||
/// Internal VAO to avoid clobbering global state.
|
/// Internal VAO to avoid clobbering global state.
|
||||||
GLuint vao, debugVAO;
|
GLuint vao, debugVAO;
|
||||||
|
|
||||||
GLuint planeVBO, skydomeVBO, skydomeIBO, debugVBO;
|
GLuint skydomeVBO, skydomeIBO, debugVBO;
|
||||||
GLuint debugTex;
|
GLuint debugTex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -347,12 +347,13 @@ void GameData::loadWaterpro(const std::string& path)
|
|||||||
std::ifstream ifstr(path.c_str());
|
std::ifstream ifstr(path.c_str());
|
||||||
|
|
||||||
if(ifstr.is_open()) {
|
if(ifstr.is_open()) {
|
||||||
uint32_t numlevels;
|
uint32_t numlevels;
|
||||||
ifstr.read(reinterpret_cast<char*>(&numlevels), sizeof(uint32_t));
|
ifstr.read(reinterpret_cast<char*>(&numlevels), sizeof(uint32_t));
|
||||||
ifstr.read(reinterpret_cast<char*>(&waterHeights), sizeof(float)*48);
|
ifstr.read(reinterpret_cast<char*>(&waterHeights), sizeof(float)*48);
|
||||||
|
|
||||||
ifstr.seekg(0x03C4);
|
ifstr.seekg(0x03C4);
|
||||||
ifstr.read(reinterpret_cast<char*>(&visibleWater), sizeof(float)*64*64);
|
ifstr.read(reinterpret_cast<char*>(&visibleWater), sizeof(float)*64*64);
|
||||||
|
ifstr.read(reinterpret_cast<char*>(&realWater), sizeof(float)*128*128);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,7 +378,7 @@ void GameData::loadWater(const std::string& path)
|
|||||||
fc = atof(c.c_str());
|
fc = atof(c.c_str());
|
||||||
fd = atof(d.c_str());
|
fd = atof(d.c_str());
|
||||||
fe = atof(e.c_str());
|
fe = atof(e.c_str());
|
||||||
waterRects.push_back({
|
waterBlocks.push_back({
|
||||||
fa,
|
fa,
|
||||||
fb,
|
fb,
|
||||||
fc,
|
fc,
|
||||||
|
@ -80,30 +80,51 @@ const char *skydomeFragmentShaderSource = "#version 130\n"
|
|||||||
"}";
|
"}";
|
||||||
const size_t skydomeSegments = 8, skydomeRows = 10;
|
const size_t skydomeSegments = 8, skydomeRows = 10;
|
||||||
|
|
||||||
|
struct WaterVertex {
|
||||||
|
static const AttributeList vertex_attributes() {
|
||||||
|
return {
|
||||||
|
{ATRS_Position, 2, sizeof(WaterVertex), 0ul}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
float planedata[] = {
|
float x, y;
|
||||||
// Vertices
|
|
||||||
1.0f, 1.0f, 0.f,
|
|
||||||
-0.0f, 1.0f, 0.f,
|
|
||||||
1.0f,-0.0f, 0.f,
|
|
||||||
-0.0f,-0.0f, 0.f,
|
|
||||||
// UV coords
|
|
||||||
1.f, 1.f,
|
|
||||||
0.f, 1.f,
|
|
||||||
1.f, 0.f,
|
|
||||||
0.f, 0.f,
|
|
||||||
// Normals
|
|
||||||
0.f, 0.f, 1.f,
|
|
||||||
0.f, 0.f, 1.f,
|
|
||||||
0.f, 0.f, 1.f,
|
|
||||||
0.f, 0.f, 1.f,
|
|
||||||
// Colours
|
|
||||||
1.f, 1.f, 1.f,
|
|
||||||
1.f, 1.f, 1.f,
|
|
||||||
1.f, 1.f, 1.f,
|
|
||||||
1.f, 1.f, 1.f
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::vector<WaterVertex> planeVerts = {
|
||||||
|
{1.0f, 1.0f},
|
||||||
|
{0.0f, 1.0f},
|
||||||
|
{1.0f,-0.0f},
|
||||||
|
{0.0f,-0.0f}
|
||||||
|
};
|
||||||
|
|
||||||
|
GeometryBuffer waterBuffer;
|
||||||
|
DrawBuffer waterDraw;
|
||||||
|
|
||||||
|
const char *waterVSSource = R"(
|
||||||
|
#version 130
|
||||||
|
#extension GL_ARB_explicit_attrib_location : enable
|
||||||
|
layout(location = 0) in vec2 position;
|
||||||
|
out vec2 TexCoords;
|
||||||
|
uniform float height;
|
||||||
|
uniform float size;
|
||||||
|
uniform mat4 MVP;
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
TexCoords = position;
|
||||||
|
gl_Position = MVP * vec4(position * size, height, 1.0);
|
||||||
|
})";
|
||||||
|
|
||||||
|
const char *waterFSSource = R"(
|
||||||
|
#version 130
|
||||||
|
in vec3 Normal;
|
||||||
|
in vec2 TexCoords;
|
||||||
|
uniform sampler2D texture;
|
||||||
|
void main() {
|
||||||
|
vec4 c = texture2D(texture, TexCoords);
|
||||||
|
gl_FragColor = c;
|
||||||
|
})";
|
||||||
|
|
||||||
|
|
||||||
GLuint compileShader(GLenum type, const char *source)
|
GLuint compileShader(GLenum type, const char *source)
|
||||||
{
|
{
|
||||||
GLuint shader = glCreateShader(type);
|
GLuint shader = glCreateShader(type);
|
||||||
@ -118,7 +139,7 @@ GLuint compileShader(GLenum type, const char *source)
|
|||||||
GLchar *buffer = new GLchar[len];
|
GLchar *buffer = new GLchar[len];
|
||||||
glGetShaderInfoLog(shader, len, NULL, buffer);
|
glGetShaderInfoLog(shader, len, NULL, buffer);
|
||||||
|
|
||||||
std::cerr << "ERROR compiling shader: " << buffer << std::endl;
|
std::cerr << "ERROR compiling shader: " << buffer << "\nSource: " << source << std::endl;
|
||||||
delete[] buffer;
|
delete[] buffer;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -162,11 +183,22 @@ GameRenderer::GameRenderer(GameWorld* engine)
|
|||||||
skyUniBottom = glGetUniformLocation(skyProgram, "BottomColor");
|
skyUniBottom = glGetUniformLocation(skyProgram, "BottomColor");
|
||||||
|
|
||||||
glGenVertexArrays( 1, &vao );
|
glGenVertexArrays( 1, &vao );
|
||||||
|
|
||||||
// prepare our special internal plane.
|
// Upload water plane
|
||||||
glGenBuffers(1, &planeVBO);
|
waterBuffer.uploadVertices(planeVerts);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
|
waterDraw.addGeometry(&waterBuffer);
|
||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(planedata), planedata, GL_STATIC_DRAW);
|
waterDraw.setFaceType(GL_TRIANGLE_STRIP);
|
||||||
|
|
||||||
|
GLuint waterVS = compileShader(GL_VERTEX_SHADER, waterVSSource);
|
||||||
|
GLuint waterFS = compileShader(GL_FRAGMENT_SHADER, waterFSSource);
|
||||||
|
waterProgram = glCreateProgram();
|
||||||
|
glAttachShader(waterProgram, waterVS);
|
||||||
|
glAttachShader(waterProgram, waterFS);
|
||||||
|
glLinkProgram(waterProgram);
|
||||||
|
waterHeight = glGetUniformLocation(waterProgram, "height");
|
||||||
|
waterTexture = glGetUniformLocation(waterProgram, "texture");
|
||||||
|
waterSize = glGetUniformLocation(waterProgram, "size");
|
||||||
|
waterMVP = glGetUniformLocation(waterProgram, "MVP");
|
||||||
|
|
||||||
// And our skydome while we're at it.
|
// And our skydome while we're at it.
|
||||||
glGenBuffers(1, &skydomeVBO);
|
glGenBuffers(1, &skydomeVBO);
|
||||||
@ -212,6 +244,11 @@ float mix(uint8_t a, uint8_t b, float num)
|
|||||||
return a+(b-a)*num;
|
return a+(b-a)*num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define GL_PLS() \
|
||||||
|
{ auto errc = glGetError(); \
|
||||||
|
if(errc != GL_NO_ERROR) std::cout << __LINE__ << ": " << errc << std::endl;\
|
||||||
|
}
|
||||||
|
|
||||||
void GameRenderer::renderWorld(float alpha)
|
void GameRenderer::renderWorld(float alpha)
|
||||||
{
|
{
|
||||||
_renderAlpha = alpha;
|
_renderAlpha = alpha;
|
||||||
@ -369,7 +406,38 @@ void GameRenderer::renderWorld(float alpha)
|
|||||||
renderSubgeometry(it->model, it->g, it->sg, it->matrix, it->object, false);
|
renderSubgeometry(it->model, it->g, it->sg, it->matrix, it->object, false);
|
||||||
}
|
}
|
||||||
transparentDrawQueue.clear();
|
transparentDrawQueue.clear();
|
||||||
|
|
||||||
|
// Draw the water.
|
||||||
|
glBindVertexArray( waterDraw.getVAOName() );
|
||||||
|
glUseProgram( waterProgram );
|
||||||
|
|
||||||
|
// TODO: label all the variables!
|
||||||
|
#define NO_WATER_INDEX 48
|
||||||
|
glm::mat4 waterModel;
|
||||||
|
glUniform1i(waterTexture, 0);
|
||||||
|
float blockSize = 4096.f/64.f;
|
||||||
|
auto waterTex = engine->gameData.textures["water_old"];
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, waterTex.texName);
|
||||||
|
|
||||||
|
// TODO: high / low quality water. Projected grid?
|
||||||
|
|
||||||
|
for( int x = 0; x < 64; x++ ) {
|
||||||
|
for( int y = 0; y < 64; y++ ) {
|
||||||
|
int i = (x*64) + y;
|
||||||
|
int hI = engine->gameData.visibleWater[i];
|
||||||
|
if( hI >= NO_WATER_INDEX ) continue;
|
||||||
|
float h = engine->gameData.waterHeights[hI];
|
||||||
|
waterModel = glm::mat4();
|
||||||
|
waterModel = glm::translate(waterModel, {-2048.f + x * blockSize, -2048.f + y * blockSize, 0.f});
|
||||||
|
glUniform1f(waterSize, blockSize);
|
||||||
|
glUniform1f(waterHeight, h);
|
||||||
|
auto MVP = proj * view * waterModel;
|
||||||
|
glUniformMatrix4fv(waterMVP, 1, GL_FALSE, glm::value_ptr(MVP));
|
||||||
|
glDrawArrays(waterDraw.getFaceType(), 0, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
glBindVertexArray( vao );
|
glBindVertexArray( vao );
|
||||||
|
|
||||||
glUseProgram(skyProgram);
|
glUseProgram(skyProgram);
|
||||||
@ -382,8 +450,8 @@ void GameRenderer::renderWorld(float alpha)
|
|||||||
glUniformMatrix4fv(skyUniProj, 1, GL_FALSE, glm::value_ptr(proj));
|
glUniformMatrix4fv(skyUniProj, 1, GL_FALSE, glm::value_ptr(proj));
|
||||||
glUniform4f(skyUniTop, skyTop.r, skyTop.g, skyTop.b, 1.f);
|
glUniform4f(skyUniTop, skyTop.r, skyTop.g, skyTop.b, 1.f);
|
||||||
glUniform4f(skyUniBottom, skyBottom.r, skyBottom.g, skyBottom.b, 1.f);
|
glUniform4f(skyUniBottom, skyBottom.r, skyBottom.g, skyBottom.b, 1.f);
|
||||||
|
|
||||||
glDrawElements(GL_TRIANGLES, skydomeSegments * skydomeRows * 6, GL_UNSIGNED_SHORT, NULL);
|
glDrawElements(GL_TRIANGLES, skydomeSegments * skydomeRows * 6, GL_UNSIGNED_SHORT, NULL);
|
||||||
|
|
||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user