push water changes (does not work yet)

This commit is contained in:
sshumakov3@gmail.com
2021-09-18 10:31:02 +03:00
parent 5b503b4ebd
commit 1cec11f3ce
29 changed files with 655 additions and 152 deletions

View File

@@ -1,7 +1,5 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#version 330 core
uniform sampler2D tex;
#version 410 core
layout (std140) uniform lighting
{
@@ -16,16 +14,85 @@ layout (std140) uniform lighting
};
uniform int type;
uniform float animtime;
uniform vec2 param;
uniform sampler2DArray texture_samplers[14] ;
in float depth_;
in vec2 tex_coord_;
in float dist_from_camera_;
flat in uint tex_array;
flat in uint type;
flat in vec2 anim_uv;
out vec4 out_color;
int get_texture_frame()
{
return int(animtime / 60) % 30;
}
vec4 get_tex_color(vec2 tex_coord, uint tex_sampler, int array_index)
{
if (tex_sampler == 0)
{
return texture(texture_samplers[0], vec3(tex_coord, array_index)).rgba;
}
else if (tex_sampler == 1)
{
return texture(texture_samplers[1], vec3(tex_coord, array_index)).rgba;
}
else if (tex_sampler == 2)
{
return texture(texture_samplers[2], vec3(tex_coord, array_index)).rgba;
}
else if (tex_sampler == 3)
{
return texture(texture_samplers[3], vec3(tex_coord, array_index)).rgba;
}
else if (tex_sampler == 4)
{
return texture(texture_samplers[4], vec3(tex_coord, array_index)).rgba;
}
else if (tex_sampler == 5)
{
return texture(texture_samplers[5], vec3(tex_coord, array_index)).rgba;
}
else if (tex_sampler == 6)
{
return texture(texture_samplers[6], vec3(tex_coord, array_index)).rgba;
}
else if (tex_sampler == 7)
{
return texture(texture_samplers[7], vec3(tex_coord, array_index)).rgba;
}
else if (tex_sampler == 8)
{
return texture(texture_samplers[8], vec3(tex_coord, array_index)).rgba;
}
else if (tex_sampler == 9)
{
return texture(texture_samplers[9], vec3(tex_coord, array_index)).rgba;
}
else if (tex_sampler == 10)
{
return texture(texture_samplers[10], vec3(tex_coord, array_index)).rgba;
}
else if (tex_sampler == 11)
{
return texture(texture_samplers[11], vec3(tex_coord, array_index)).rgba;
}
else if (tex_sampler == 12)
{
return texture(texture_samplers[12], vec3(tex_coord, array_index)).rgba;
}
else if (tex_sampler == 13)
{
return texture(texture_samplers[13], vec3(tex_coord, array_index)).rgba;
}
return vec4(0);
}
vec2 rot2(vec2 p, float degree)
{
float a = radians(degree);
@@ -37,12 +104,12 @@ void main()
// lava || slime
if(type == 2 || type == 3)
{
out_color = texture(tex, tex_coord_ + vec2(param.x*animtime, param.y*animtime));
out_color = get_tex_color(tex_coord_ + vec2(anim_uv.x*animtime, anim_uv.y*animtime), tex_array, get_texture_frame());
}
else
{
vec2 uv = rot2(tex_coord_ * param.x, param.y);
vec4 texel = texture(tex, uv);
vec2 uv = rot2(tex_coord_ * anim_uv.x, anim_uv.y);
vec4 texel = get_tex_color(uv, tex_array, get_texture_frame());
vec4 lerp = (type == 1)
? mix (OceanColorLight, OceanColorDark, depth_)
: mix (RiverColorLight, RiverColorDark, depth_)
@@ -70,4 +137,6 @@ void main()
out_color.rgb = mix(out_color.rgb, FogColor_FogOn.rgb, fogFactor);
}
out_color = vec4(0, 0, 0, 1);
}

View File

@@ -1,18 +1,39 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#version 330 core
#version 410 core
in vec4 position;
in vec2 tex_coord;
in float depth;
const float TILESIZE = 533.33333f;
const float CHUNKSIZE = ((TILESIZE) / 16.0f);
const float UNITSIZE = (CHUNKSIZE / 8.0f);
in vec2 position;
uniform vec3 camera;
struct LiquidChunkInstanceDataUniformBlock
{
uint texture_array;
uint type;
float xbase;
float zbase;
float anim_u;
float anim_v;
uint subchunks_1;
uint subchunks_2;
};
layout (std140) uniform matrices
{
mat4 model_view;
mat4 projection;
};
layout (std140) uniform liquid_layers_params
{
LiquidChunkInstanceDataUniformBlock[256] layer_params;
};
uniform sampler2DArray vertex_data;
uniform mat4 transform;
uniform int use_transform = int(0);
@@ -20,19 +41,60 @@ uniform int use_transform = int(0);
out float depth_;
out vec2 tex_coord_;
out float dist_from_camera_;
flat out uint tex_array;
flat out uint type;
flat out vec2 anim_uv;
bool hasSubchunk(uint x, uint z, uint subchunks_first, uint subchunks_second)
{
return bool((subchunks_second >> (z * 8 + x - 32 * uint(z < 4))) & 1u);
}
float makeNaN(float nonneg)
{
return sqrt(-nonneg-1.0);
}
void main()
{
depth_ = depth;
tex_coord_ = tex_coord;
dist_from_camera_ = distance(camera, position.xyz);
uint vertex_x = uint(position.x / UNITSIZE);
uint vertex_y = uint(position.y / UNITSIZE);
if(use_transform == 1)
vec4 v_data = texelFetch(vertex_data, ivec3(vertex_x, vertex_y, gl_InstanceID), 0);
LiquidChunkInstanceDataUniformBlock params = layer_params[gl_InstanceID];
uint sschunk = gl_VertexID / 3 / 2;
uint schunk_x = sschunk % 8;
uint schunk_z = sschunk / 8;
vec4 final_pos;
if (hasSubchunk(schunk_x, schunk_z, params.subchunks_1, params.subchunks_2))
{
gl_Position = projection * model_view * transform * position;
final_pos = vec4(position.x + params.xbase, v_data.r, position.y + params.zbase, 1.0);
}
else
{
gl_Position = projection * model_view * position;
float NaN = makeNaN(1);
final_pos = vec4(NaN, NaN, NaN, NaN);
}
final_pos = vec4(position.x + params.xbase, 0, position.y + params.zbase, 1.0);
depth_ = v_data.g;
tex_coord_ = v_data.ba;
dist_from_camera_ = distance(camera, final_pos.xyz);
tex_array = params.texture_array;
type = params.type;
anim_uv = vec2(params.anim_u, params.anim_v);
if(use_transform == 1)
{
gl_Position = projection * model_view * transform * final_pos;
}
else
{
gl_Position = projection * model_view * final_pos;
}
}

View File

@@ -44,10 +44,23 @@ void ChunkWater::from_mclq(std::vector<mclq>& layers)
switch (mclq_liquid_type)
{
case 1:_layers.emplace_back(this, pos, liquid, 2); break;
case 3:_layers.emplace_back(this, pos, liquid, 4); break;
case 4:_layers.emplace_back(this, pos, liquid, 1); break;
case 6:_layers.emplace_back(this, pos, liquid, (_use_mclq_green_lava ? 15 : 3)); break;
case 1:
_layers.emplace_back(this, pos, liquid, 2);
_water_tile->markBuffersDirty();
break;
case 3:
_layers.emplace_back(this, pos, liquid, 4);
_water_tile->markBuffersDirty();
break;
case 4:
_layers.emplace_back(this, pos, liquid, 1);
_water_tile->markBuffersDirty();
break;
case 6:
_layers.emplace_back(this, pos, liquid, (_use_mclq_green_lava ? 15 : 3));
_water_tile->markBuffersDirty();
break;
default:
LogError << "Invalid/unhandled MCLQ liquid type" << std::endl;
break;
@@ -94,6 +107,7 @@ void ChunkWater::fromFile(MPQFile &f, size_t basePos)
math::vector_3d pos(xbase, 0.0f, zbase);
_layers.emplace_back(this, f, basePos, pos, info, infoMask);
_water_tile->markBuffersDirty();
}
update_layers();
@@ -259,6 +273,8 @@ void ChunkWater::paintLiquid( math::vector_3d const& pos
liquid_layer layer(this, math::vector_3d(xbase, 0.0f, zbase), pos.y, liquid_id);
copy_height_to_layer(layer, pos, radius);
_layers.push_back(layer);
_water_tile->markBuffersDirty();
}
}
@@ -292,12 +308,14 @@ void ChunkWater::paintLiquid( math::vector_3d const& pos
layer.paintLiquid(pos, radius, true, angle, orientation, lock, origin, override_height, chunk, opacity_factor);
layer.changeLiquidID(liquid_id);
_layers.push_back(layer);
_water_tile->markBuffersDirty();
}
else
{
liquid_layer layer(this, math::vector_3d(xbase, 0.0f, zbase), pos.y, liquid_id);
layer.paintLiquid(pos, radius, true, angle, orientation, lock, origin, override_height, chunk, opacity_factor);
_layers.push_back(layer);
_water_tile->markBuffersDirty();
}
update_layers();
@@ -309,6 +327,7 @@ void ChunkWater::cleanup()
{
if (_layers[i].empty())
{
_water_tile->unregisterChunkLayer(&*(_layers.begin() + i));
_layers.erase(_layers.begin() + i);
}
}

View File

@@ -55,7 +55,7 @@ void LiquidTextureManager::upload()
// init 2D texture array
// loading a texture is required to get its dimensions and format
blp_texture tex(boost::str(boost::format(filename) % i), _context);
blp_texture tex(boost::str(boost::format(filename) % 1), _context);
tex.finishLoading();
int width_ = tex.width();
@@ -95,7 +95,7 @@ void LiquidTextureManager::upload()
for (int j = 0; j < N_FRAMES; ++j)
{
blp_texture tex_frame(boost::str(boost::format(filename) % j), _context);
blp_texture tex_frame(boost::str(boost::format(filename) % (j + 1)), _context);
tex_frame.finishLoading();
// error checking

View File

@@ -426,15 +426,15 @@ void MapTile::draw ( math::frustum const& frustum
// figure out if we need to update based on paintability
bool need_paintability_update = false;
if (draw_paintability_overlay && show_unpaintable_chunks)
if (_requires_paintability_recalc && draw_paintability_overlay && show_unpaintable_chunks)
[[unlikely]]
{
auto cur_tex = noggit::ui::selected_texture::get();
for (int j = 0; j < 16; ++j)
{
for (int i = 0; i < 16; ++i)
{
auto& chunk = mChunks[j][i];
auto cur_tex = noggit::ui::selected_texture::get();
bool cant_paint = cur_tex && !chunk->canPaintTexture(*cur_tex);
if (chunk->currently_paintable != !cant_paint)
@@ -445,6 +445,8 @@ void MapTile::draw ( math::frustum const& frustum
}
}
}
_requires_paintability_recalc = false;
}
// run chunk updates. running this when splitdraw call detected unused sampler configuration as well.
@@ -851,11 +853,11 @@ void MapTile::drawWater ( math::frustum const& frustum
, const float& cull_distance
, const math::vector_3d& camera
, bool camera_moved
, liquid_render& render
, opengl::scoped::use_program& water_shader
, int animtime
, int layer
, display_mode display
, LiquidTextureManager* tex_manager
)
{
if (!Water.hasData(0))
@@ -867,11 +869,11 @@ void MapTile::drawWater ( math::frustum const& frustum
, cull_distance
, camera
, camera_moved
, render
, water_shader
, animtime
, layer
, display
, tex_manager
);
}

View File

@@ -95,11 +95,11 @@ public:
, const float& cull_distance
, const math::vector_3d& camera
, bool camera_moved
, liquid_render& render
, opengl::scoped::use_program& water_shader
, int animtime
, int layer
, display_mode display
, LiquidTextureManager* tex_manager
);
void drawMFBO (opengl::scoped::use_program&);
@@ -155,6 +155,8 @@ public:
GLuint getAlphamapTextureHandle() { return _alphamap_tex; };
World* getWorld() { return _world; };
void notifyTileRendererOnSelectedTextureChange() { _requires_paintability_recalc = true; }
private:
void uploadTextures();
@@ -165,6 +167,7 @@ private:
bool _selected = false;
bool _split_drawcall = false;
bool _requires_sampler_reset = true;
bool _requires_paintability_recalc = true;
std::array<math::vector_3d, 2> _extents;

View File

@@ -655,7 +655,12 @@ void MapView::setupTexturePainterUi()
, &_show_texture_palette_small_window, &noggit::bool_toggle_property::set
);
connect(texturingTool->_current_texture, &noggit::ui::current_texture::texture_updated
, [=]()
{
_world->notifyTileRendererOnSelectedTextureChange();
}
);
/* Texture Picker */

View File

@@ -248,7 +248,7 @@ void PreviewRenderer::draw()
wmo_instance.draw(
wmo_program, model_view().transposed(), projection().transposed(), frustum, culldistance,
math::vector_3d(0.0f, 0.0f, 0.0f), _draw_boxes.get(), _draw_models.get() // doodads
, false, _liquid_render.get(), std::vector<selection_type>(), 0, false, display_mode::in_3D
, false, std::vector<selection_type>(), 0, false, display_mode::in_3D
);
gl.enable(GL_BLEND);

View File

@@ -322,8 +322,14 @@ void blp_texture::loadFromUncompressedData(BLPHeader const* lHeader, char const*
{
unsigned int k = pal[*c++];
k = ((k & 0x00FF0000) >> 16) | ((k & 0x0000FF00)) | ((k & 0x000000FF) << 16);
int alpha = 0xFF;
if (hasalpha)
if (_is_tileset && !_is_specular)
{
alpha = 0x00;
}
else if (hasalpha)
{
if (alphabits == 8)
{
@@ -414,6 +420,8 @@ void blp_texture::finishLoading()
if (filename.starts_with("tileset/"))
{
_is_tileset = true;
spec_filename = filename.substr(0, filename.find_last_of(".")) + "_s.blp";
has_specular = MPQFile::exists(spec_filename);

View File

@@ -85,6 +85,7 @@ private:
noggit::NoggitRenderContext _context;
bool _is_specular = false;
bool _is_tileset = false;
private:
std::map<int, std::vector<uint32_t>> _data;

View File

@@ -6,18 +6,22 @@
#include <noggit/Misc.h>
#include <noggit/TileWater.hpp>
#include <noggit/liquid_layer.hpp>
#include <stdexcept>
#include <noggit/World.h>
#include <noggit/LiquidTextureManager.hpp>
#include <stdexcept>
#include <iterator>
TileWater::TileWater(MapTile *pTile, float pXbase, float pZbase, bool use_mclq_green_lava)
: tile(pTile)
, xbase(pXbase)
, zbase(pZbase)
, _update_flags(ll_HEIGHT || ll_DEPTH || ll_UV || ll_FLAGS || ll_TYPE)
{
// by default we allocate space only for one liquid layer
_chunk_instances.reserve(256);
_chunk_layer_refs.reserve(256);
_chunk_instance_indices.reserve(256);
_chunk_layer_ptrs.reserve(256);
_chunk_data.reserve(256);
for (int z = 0; z < 16; ++z)
{
@@ -44,29 +48,66 @@ void TileWater::draw ( math::frustum const& frustum
, const float& cull_distance
, const math::vector_3d& camera
, bool camera_moved
, liquid_render& render
, opengl::scoped::use_program& water_shader
, int animtime
, int layer
, display_mode display
, LiquidTextureManager* tex_manager
)
{
for (int z = 0; z < 16; ++z)
constexpr int N_SAMPLERS = 14;
static std::vector<int> samplers_upload_buf {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
if (!_loaded)
[[unlikely]]
{
for (int x = 0; x < 16; ++x)
{
chunks[z][x]->draw ( frustum
, cull_distance
, camera
, camera_moved
, render
, water_shader
, animtime
, layer
, display
);
}
upload();
}
updateLayerData(tex_manager);
std::size_t n_render_blocks = _liquid_vertex_data_textures.size();
for (std::size_t i = 0; i < n_render_blocks; ++i)
{
std::size_t chunk_index = i % 256;
gl.bindBuffer(GL_UNIFORM_BUFFER, _liquid_parameters_buffers[i]);
gl.bindBufferRange(GL_UNIFORM_BUFFER, opengl::ubo_targets::CHUNK_LIQUID_INSTANCE_INDEX, _liquid_vertex_data_textures[i], 0, sizeof(opengl::LiquidChunkInstanceDataUniformBlock));
gl.activeTexture(GL_TEXTURE0);
gl.bindTexture(GL_TEXTURE_2D_ARRAY, _liquid_vertex_data_textures[i]);
if (_chunk_layer_texture_samplers[i].size() > N_SAMPLERS)
[[unlikely]] // multi draw-call mode
{
// TODO:
}
else
{
std::fill(samplers_upload_buf.begin(), samplers_upload_buf.end(), -1);
for (std::size_t j = 0; j < _chunk_layer_texture_samplers[i].size(); ++j)
{
samplers_upload_buf[j] = _chunk_layer_texture_samplers[i][j];
}
for (std::size_t j = 0; j < N_SAMPLERS; ++j)
{
if (samplers_upload_buf[j] < 0)
break;
gl.activeTexture(GL_TEXTURE0 + 2 + j);
gl.bindTexture(GL_TEXTURE_2D_ARRAY, samplers_upload_buf[j]);
}
gl.drawArraysInstanced(GL_TRIANGLES, 0, 8 * 8 * 6, std::min(static_cast<unsigned>(_n_chunk_instances - (i * 256)),
256u));
}
}
}
ChunkWater* TileWater::getChunk(int x, int z)
@@ -162,64 +203,219 @@ int TileWater::getType(size_t layer)
return 0;
}
void TileWater::registerChunkLayerUpdate(unsigned flags)
{
_update_flags |= flags;
}
void TileWater::updateLayerData(LiquidTextureManager* tex_manager)
{
tsl::robin_map<unsigned, std::tuple<GLuint, math::vector_2d, int>> const& tex_frames = tex_manager->getTextureFrames();
// create opengl resources if needed
if (_need_buffer_update)
{
// alloc or realloc index texture
/*
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
gl.bindTexture(GL_TEXTURE_2D, _liquid_chunk_index_texture);
gl.texImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 9, 9, 0, GL_R, GL_UNSIGNED_INT, nullptr);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
*/
_chunk_layer_ptrs.clear();
_chunk_data.clear();
_chunk_layer_ptrs.reserve(256);
_chunk_data.reserve(256);
_n_chunk_instances = 0;
for (std::size_t z = 0; z < 16; ++z)
{
for (std::size_t x = 0; x < 16; ++x)
{
for (auto& layer : *chunks[z][x]->getLayers())
{
_chunk_layer_ptrs.emplace_back(&layer);
_chunk_data.emplace_back();
_n_chunk_instances++;
}
}
}
// grow
while (_liquid_vertex_data_textures.size() * 256 < _n_chunk_instances)
{
GLuint& data_tex = _liquid_vertex_data_textures.emplace_back();
gl.genTextures(1, &data_tex);
gl.bindTexture(GL_TEXTURE_2D_ARRAY, data_tex);
gl.texImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, 9, 9, 256, 0, GL_RGBA, GL_FLOAT, nullptr);
gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 0);
GLuint& buf = _liquid_parameters_buffers.emplace_back();
gl.genBuffers(1, &buf);
gl.bindBuffer(GL_UNIFORM_BUFFER, buf);
gl.bufferData(GL_UNIFORM_BUFFER, sizeof(opengl::LiquidChunkInstanceDataUniformBlock) * 256, NULL, GL_DYNAMIC_DRAW);
gl.bindBufferRange(GL_UNIFORM_BUFFER, opengl::ubo_targets::CHUNK_LIQUID_INSTANCE_INDEX, buf, 0, sizeof(opengl::LiquidChunkInstanceDataUniformBlock));
_chunk_layer_texture_samplers.emplace_back();
}
// shrink
while (_liquid_vertex_data_textures.size() * 256 > _n_chunk_instances && _liquid_vertex_data_textures.size() * 256 - _n_chunk_instances % 256 >= 256)
{
GLuint data_tex = _liquid_vertex_data_textures.back();
gl.deleteTextures(1, &data_tex);
_liquid_vertex_data_textures.pop_back();
GLuint params_buf = _liquid_parameters_buffers.back();
gl.deleteBuffers(1, &params_buf);
_liquid_parameters_buffers.pop_back();
_chunk_layer_texture_samplers.pop_back();
}
// vertex data
unsigned cur_buf_index = 0;
for (std::size_t i = 0; i < _chunk_layer_ptrs.size(); ++i)
{
unsigned tex_index = i % 256;
if (!tex_index)
{
gl.bindTexture(GL_TEXTURE_2D_ARRAY, _liquid_vertex_data_textures[cur_buf_index]);
gl.bindBuffer(GL_UNIFORM_BUFFER, _liquid_parameters_buffers[cur_buf_index]);
cur_buf_index++;
}
prepareBufferData(i);
gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, tex_index, 9, 9, 1, GL_RGBA, GL_FLOAT, &_chunk_data[i]);
// per layer chunk params
liquid_layer* layer = _chunk_layer_ptrs[i];
std::tuple<GLuint, math::vector_2d, int> const& tex_profile = tex_frames.at(layer->liquidID());
opengl::LiquidChunkInstanceDataUniformBlock params_data{};
params_data.xbase = layer->getChunk()->xbase;
params_data.zbase = layer->getChunk()->zbase;
GLuint tex_array = std::get<0>(tex_profile);
std::vector<int>& samplers_array = _chunk_layer_texture_samplers[cur_buf_index - 1];
auto it = std::find(samplers_array.begin(), samplers_array.end(), tex_array);
unsigned sampler_index = 0;
if (it != samplers_array.end())
{
sampler_index = std::distance(samplers_array.begin(), it);
}
else
{
sampler_index = samplers_array.size();
samplers_array.emplace_back(std::get<0>(tex_profile));
}
params_data.texture_array = sampler_index;
params_data.type = std::get<2>(tex_profile);
math::vector_2d anim = std::get<1>(tex_profile);
params_data.anim_u = anim.x;
params_data.anim_v = anim.y;
std::uint64_t subchunks = layer->getSubchunks();
params_data.subchunks_1 = subchunks & 0xFF'FF'FF'FFull << 32;
params_data.subchunks_2 = subchunks & 0xFF'FF'FF'FF;
gl.bufferSubData(GL_UNIFORM_BUFFER, tex_index * sizeof(opengl::LiquidChunkInstanceDataUniformBlock), sizeof(opengl::LiquidChunkInstanceDataUniformBlock), &params_data);
}
_need_buffer_update = false;
}
}
void TileWater::upload()
{
_buffers.upload();
gl.genTextures(1, &_liquid_chunk_index_texture);
_loaded = true;
}
void TileWater::unload()
{
_buffers.unload();
gl.deleteTextures(_liquid_vertex_data_textures.size(), _liquid_vertex_data_textures.data());
gl.deleteBuffers(_liquid_parameters_buffers.size(), _liquid_parameters_buffers.data());
_liquid_vertex_data_textures.clear();
_liquid_parameters_buffers.clear();
_liquid_vertex_data_textures.clear();
gl.deleteTextures(1, &_liquid_chunk_index_texture);
//gl.deleteTextures(0, &_liquid_vertex_data);
_update_flags = ll_HEIGHT || ll_DEPTH || ll_UV || ll_FLAGS || ll_TYPE;
_loaded = false;
_need_buffer_update = true;
}
void TileWater::registerChunkLayer(liquid_layer* layer)
{
if (_chunk_layer_refs.capacity() == _chunk_layer_refs.size())
{
_chunk_layer_refs.reserve(_chunk_layer_refs.capacity() + 256);
}
if (_chunk_instances.capacity() == _chunk_instances.size())
{
_chunk_instances.reserve(_chunk_instances.capacity() + 256);
}
_chunk_layer_refs.emplace_back(layer);
opengl::LiquidChunkInstanceDataUniformBlock chunk_instance{};
MapChunk* chunk = layer->getChunk()->getChunk();
//chunk_instance.BaseHeight_ChunkXY_Pad1[1] = chunk->mt->xbase + (chunk->px * CHUNKSIZE);
//chunk_instance.BaseHeight_ChunkXY_Pad1[2] = chunk->mt->zbase + (chunk->py * CHUNKSIZE);
_chunk_instances.push_back(chunk_instance);
_chunk_layer_ptrs.emplace_back(layer);
_chunk_instance_indices.emplace_back(_n_layer_chunks);
_chunk_data.emplace_back();
_chunk_layer_texture_samplers.clear();
_n_layer_chunks++;
_need_buffer_update = true;
}
void TileWater::unregisterChunkLayer(liquid_layer* layer)
{
auto it = std::find(_chunk_layer_refs.begin(), _chunk_layer_refs.end(), layer);
auto it = std::find(_chunk_layer_ptrs.begin(), _chunk_layer_ptrs.end(), layer);
if (it != _chunk_layer_refs.end())
if (it != _chunk_layer_ptrs.end())
{
int index = it - _chunk_layer_ptrs.begin();
_chunk_instance_indices.erase(_chunk_instance_indices.begin() + index);
_chunk_data.erase(_chunk_data.begin() + index);
_chunk_layer_ptrs.erase(it);
_n_layer_chunks--;
// shrink the container
if (_chunk_layer_ptrs.capacity() > _chunk_layer_ptrs.size() && _chunk_layer_ptrs.capacity() - _chunk_layer_ptrs.size() >= 256)
{
_chunk_instance_indices.resize(_chunk_layer_ptrs.size());
_chunk_layer_ptrs.resize(_chunk_layer_ptrs.size());
_chunk_data.resize(_chunk_data.size());
}
_need_buffer_update = true;
_chunk_layer_texture_samplers.clear();
int index = it - _chunk_layer_refs.begin();
_chunk_layer_refs.erase(it);
_chunk_instances.erase(_chunk_instances.begin() + index);
}
else
{
throw std::logic_error("Tried unregistering already freed liquid chunk");
}
}
void TileWater::updateChunkLayer(liquid_layer* layer)
void TileWater::prepareBufferData(std::size_t layer_index)
{
auto it = std::find(_chunk_layer_refs.begin(), _chunk_layer_refs.end(), layer);
liquid_layer* layer = _chunk_layer_ptrs[layer_index];
std::array<math::vector_4d, 9 * 9>& chunk_layer_data = _chunk_data.at(layer_index);
if (it != _chunk_layer_refs.end())
auto& vertices = layer->getVertices();
auto& tex_coords = layer->getTexCoords();
auto& depth = layer->getDepth();
for (int z = 0; z < 9; ++z)
{
int index = it - _chunk_layer_refs.begin();
opengl::LiquidChunkInstanceDataUniformBlock& instance = _chunk_instances[index];
auto const& texture_frames = tile->getWorld()->getLiquidTextureManager()->getTextureFrames();
std::tuple<GLuint, math::vector_2d, int> const& lq_layer_texture_params = texture_frames.at(layer->liquidID());
instance.TextureArray_Pad3[0] = std::get<0>(lq_layer_texture_params);
for (int x = 0; x < 9; ++x)
{
const unsigned v_index = z * 9 + x;
math::vector_2d& tex_coord = tex_coords[v_index];
chunk_layer_data[v_index] = math::vector_4d(vertices[v_index].y, depth[v_index], tex_coord.x, tex_coord.y);
}
}
else
{
throw std::logic_error("Tried updating non-existing liquid chunk");
}
}
}

View File

@@ -3,22 +3,35 @@
#pragma once
#include <math/vector_3d.hpp>
#include <math/vector_4d.hpp>
#include <noggit/ChunkWater.hpp>
#include <noggit/MPQ.h>
#include <noggit/MapHeaders.h>
#include <noggit/tool_enums.hpp>
#include <opengl/context.hpp>
#include <opengl/types.hpp>
#include <noggit/LiquidTextureManager.hpp>
#include <memory>
#include <vector>
#include <array>
#include <set>
class MapTile;
class liquid_layer;
class sExtendableArray;
enum LiquidLayerUpdateFlags;
class TileWater
{
struct LiquidTexBinding
{
unsigned tex_array;
unsigned type;
unsigned pad0;
unsigned pad1;
};
public:
TileWater(MapTile *pTile, float pXbase, float pZbase, bool use_mclq_green_lava);
@@ -31,11 +44,11 @@ public:
, const float& cull_distance
, const math::vector_3d& camera
, bool camera_moved
, liquid_render& render
, opengl::scoped::use_program& water_shader
, int animtime
, int layer
, display_mode display
, LiquidTextureManager* tex_manager
);
bool hasData(size_t layer);
void CropMiniChunk(int x, int z, MapChunk* chunkTerrain);
@@ -47,14 +60,39 @@ public:
void registerChunkLayer(liquid_layer* layer);
void unregisterChunkLayer(liquid_layer* layer);
void updateChunkLayer(liquid_layer* layer);
void registerChunkLayerUpdate(unsigned flags);
void doneChunkLayerUpdate() { _update_flags = 0; };
void markBuffersDirty() { _need_buffer_update = true; };
void updateLayerData(LiquidTextureManager* tex_manager);
void prepareBufferData(std::size_t layer_index);
void unload();
void upload();
private:
MapTile *tile;
std::unique_ptr<ChunkWater> chunks[16][16];
std::vector<opengl::LiquidChunkInstanceDataUniformBlock> _chunk_instances;
std::vector<liquid_layer*> _chunk_layer_refs;
std::vector<unsigned> _chunk_instance_indices;
std::vector<std::array<math::vector_4d, 9 * 9>> _chunk_data;
std::vector<liquid_layer*> _chunk_layer_ptrs;
std::vector<std::vector<int>> _chunk_layer_texture_samplers;
std::size_t _n_chunk_instances = 256;
opengl::scoped::deferred_upload_buffers<1> _buffers;
std::vector<GLuint> _liquid_vertex_data_textures;
std::vector<GLuint> _liquid_parameters_buffers;
GLuint _liquid_chunk_index_texture = 0;
unsigned _n_layer_chunks = 0;
bool _need_buffer_update = false;
bool _loaded = false;
unsigned _update_flags;
float xbase;
float zbase;

View File

@@ -332,7 +332,6 @@ void WMO::draw ( opengl::scoped::use_program& wmo_shader
, const math::vector_3d& camera
, bool // draw_doodads
, bool draw_fog
, liquid_render& render
, int animtime
, bool world_has_skies
, display_mode display
@@ -360,11 +359,14 @@ void WMO::draw ( opengl::scoped::use_program& wmo_shader
, world_has_skies
);
/*
group.drawLiquid ( transform_matrix_transposed
, render
, draw_fog
, animtime
);
*/
}
if (boundingbox)

View File

@@ -266,7 +266,6 @@ public:
, const math::vector_3d& camera
, bool draw_doodads
, bool draw_fog
, liquid_render& render
, int animtime
, bool world_has_skies
, display_mode display

View File

@@ -54,7 +54,6 @@ void WMOInstance::draw ( opengl::scoped::use_program& wmo_shader
, bool force_box
, bool draw_doodads
, bool draw_fog
, liquid_render& render
, std::vector<selection_type> selection
, int animtime
, bool world_has_skies
@@ -95,7 +94,6 @@ void WMOInstance::draw ( opengl::scoped::use_program& wmo_shader
, camera
, draw_doodads
, draw_fog
, render
, animtime
, world_has_skies
, display

View File

@@ -95,7 +95,6 @@ public:
, bool force_box
, bool draw_doodads
, bool draw_fog
, liquid_render& render
, std::vector<selection_type> selection
, int animtime
, bool world_has_skies

View File

@@ -860,10 +860,7 @@ void World::initShaders()
}
);
}
if (!_liquid_render)
{
_liquid_render.emplace(_context);
}
if (!_wmo_program)
{
_wmo_program.reset
@@ -874,6 +871,16 @@ void World::initShaders()
);
}
if (!_liquid_program)
{
_liquid_program.reset(
new opengl::program
{ { GL_VERTEX_SHADER, opengl::shader::src_from_qrc("liquid_vs") }
, { GL_FRAGMENT_SHADER, opengl::shader::src_from_qrc("liquid_fs") }
}
);
}
_liquid_texture_manager.upload();
{
@@ -959,9 +966,19 @@ void World::initShaders()
*/
{
opengl::scoped::use_program liquid_render {_liquid_render.get().shader_program()};
opengl::scoped::use_program liquid_render {*_liquid_program.get()};
setupLiquidChunkBuffers();
setupLiquidChunkVAO(liquid_render);
static std::vector<int> samplers {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
liquid_render.bind_uniform_block("matrices", 0);
liquid_render.bind_uniform_block("lighting", 1);
liquid_render.bind_uniform_block("liquid_layers_params", 4);
liquid_render.uniform("vertex_data", 0);
liquid_render.uniform("texture_samplers", samplers);
}
{
@@ -1214,7 +1231,6 @@ void World::draw ( math::matrix_4x4 const& model_view
, is_hidden
, draw_wmo_doodads
, draw_fog
, _liquid_render.get()
, current_selection()
, animtime
, skies->hasSkies()
@@ -1354,7 +1370,7 @@ void World::draw ( math::matrix_4x4 const& model_view
// set anim time only once per frame
{
opengl::scoped::use_program water_shader {_liquid_render->shader_program()};
opengl::scoped::use_program water_shader {*_liquid_program.get()};
water_shader.uniform("animtime", static_cast<float>(animtime) / 2880.f);
water_shader.uniform("camera", camera_pos);
@@ -1409,12 +1425,13 @@ void World::draw ( math::matrix_4x4 const& model_view
if (draw_water)
{
ZoneScopedN("World::draw() : Draw water");
_liquid_render->force_texture_update();
// draw the water on both sides
opengl::scoped::bool_setter<GL_CULL_FACE, GL_FALSE> const cull;
opengl::scoped::use_program water_shader{ _liquid_render->shader_program() };
opengl::scoped::use_program water_shader{ *_liquid_program.get()};
gl.bindVertexArray(_liquid_chunk_vao);
water_shader.uniform ("use_transform", 0);
@@ -1424,16 +1441,15 @@ void World::draw ( math::matrix_4x4 const& model_view
, culldistance
, camera_pos
, camera_moved
, _liquid_render.get()
, water_shader
, animtime
, water_layer
, display
, &_liquid_texture_manager
);
}
gl.bindVertexArray(0);
gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
gl.disable(GL_BLEND);
@@ -3672,6 +3688,7 @@ void World::unload_shaders()
_m2_ribbons_program.reset();
_m2_box_program.reset();
_wmo_program.reset();
_liquid_program.reset();
_mcnk_program_mini.reset();
_m2_program_mini.reset();
@@ -3683,8 +3700,6 @@ void World::unload_shaders()
_square_render.unload();
_horizon_render.reset();
_liquid_render = boost::none;
_liquid_render_mini = boost::none;
_liquid_texture_manager.unload();
skies->unload();
@@ -4411,3 +4426,11 @@ void World::setupLiquidChunkBuffers()
}
void World::notifyTileRendererOnSelectedTextureChange()
{
for (MapTile* tile : mapIndex.loaded_tiles())
{
tile->notifyTileRendererOnSelectedTextureChange();
}
}

View File

@@ -295,7 +295,7 @@ public:
void ensureAllTilesetsADT(math::vector_3d const& pos);
void ensureAllTilesetsAllADTs();
void notifyTileRendererOnSelectedTextureChange();
void addM2 ( std::string const& filename
, math::vector_3d newPos
@@ -453,6 +453,7 @@ private:
std::unique_ptr<opengl::program> _m2_ribbons_program;
std::unique_ptr<opengl::program> _m2_box_program;
std::unique_ptr<opengl::program> _wmo_program;
std::unique_ptr<opengl::program> _liquid_program;
// Minimap programs. Ugly, but those can't be shared between contexts, so we compile twice
std::unique_ptr<opengl::program> _mcnk_program_mini;
@@ -464,9 +465,6 @@ private:
opengl::primitives::sphere _sphere_render;
opengl::primitives::square _square_render;
boost::optional<liquid_render> _liquid_render = boost::none;
boost::optional<liquid_render> _liquid_render_mini = boost::none;
noggit::NoggitRenderContext _context;
opengl::scoped::deferred_upload_buffers<7> _buffers;

View File

@@ -33,9 +33,11 @@ liquid_layer::liquid_layer(ChunkWater* chunk, math::vector_3d const& base, float
{
for (int x = 0; x < 9; ++x)
{
_tex_coords.emplace_back(default_uv(x, z));
_depth.emplace_back(1.0f);
_vertices.emplace_back( pos.x + UNITSIZE * x
unsigned v_index = z * 9 + x;
_tex_coords[v_index] = default_uv(x, z);
_depth[v_index] = 1.0f;
_vertices[v_index] = math::vector_3d(
pos.x + UNITSIZE * x
, height
, pos.z + UNITSIZE * z
);
@@ -43,7 +45,7 @@ liquid_layer::liquid_layer(ChunkWater* chunk, math::vector_3d const& base, float
}
changeLiquidID(_liquid_id);
chunk->getWaterTile()->registerChunkLayer(this);
}
liquid_layer::liquid_layer(ChunkWater* chunk, math::vector_3d const& base, mclq& liquid, int liquid_id)
@@ -68,20 +70,22 @@ liquid_layer::liquid_layer(ChunkWater* chunk, math::vector_3d const& base, mclq&
{
for (int x = 0; x < 9; ++x)
{
mclq_vertex const& v = liquid.vertices[z * 9 + x];
const unsigned v_index = z * 9 + x;
mclq_vertex const& v = liquid.vertices[v_index];
if (_liquid_vertex_format == 1)
{
_depth.emplace_back(1.0f);
_tex_coords.emplace_back(static_cast<float>(v.magma.x) / 255.f, static_cast<float>(v.magma.y) / 255.f);
_depth[v_index] = 1.0f;
_tex_coords[v_index] = math::vector_2d(static_cast<float>(v.magma.x) / 255.f, static_cast<float>(v.magma.y) / 255.f);
}
else
{
_depth.emplace_back(static_cast<float>(v.water.depth) / 255.f);
_tex_coords.emplace_back(default_uv(x, z));
_depth[v_index] = static_cast<float>(v.water.depth) / 255.f;
_tex_coords[v_index] = default_uv(x, z);
}
_vertices.emplace_back( pos.x + UNITSIZE * x
_vertices[v_index] = math::vector_3d(
pos.x + UNITSIZE * x
// sometimes there's garbage data on unused tiles that mess things up
, std::max(std::min(v.height, _maximum), _minimum)
, pos.z + UNITSIZE * z
@@ -89,7 +93,6 @@ liquid_layer::liquid_layer(ChunkWater* chunk, math::vector_3d const& base, mclq&
}
}
chunk->getWaterTile()->registerChunkLayer(this);
}
liquid_layer::liquid_layer(ChunkWater* chunk, MPQFile &f, std::size_t base_pos, math::vector_3d const& base, MH2O_Information const& info, std::uint64_t infomask)
@@ -116,9 +119,11 @@ liquid_layer::liquid_layer(ChunkWater* chunk, MPQFile &f, std::size_t base_pos,
{
for (int x = 0; x < 9; ++x)
{
_tex_coords.emplace_back(default_uv(x, z));
_depth.emplace_back(1.0f);
_vertices.emplace_back(pos.x + UNITSIZE * x
const unsigned v_index = z * 9 + x;
_tex_coords[v_index] = default_uv(x, z);
_depth[v_index] = 1.0f;
_vertices[v_index] = math::vector_3d(
pos.x + UNITSIZE * x
, _minimum
, pos.z + UNITSIZE * z
);
@@ -171,7 +176,7 @@ liquid_layer::liquid_layer(ChunkWater* chunk, MPQFile &f, std::size_t base_pos,
}
}
chunk->getWaterTile()->registerChunkLayer(this);
}
liquid_layer::liquid_layer(liquid_layer&& other)
@@ -189,7 +194,6 @@ liquid_layer::liquid_layer(liquid_layer&& other)
, _chunk(other._chunk)
{
changeLiquidID(_liquid_id);
_chunk->getWaterTile()->registerChunkLayer(this);
}
liquid_layer::liquid_layer(liquid_layer const& other)
@@ -207,7 +211,6 @@ liquid_layer::liquid_layer(liquid_layer const& other)
, _chunk(other._chunk)
{
changeLiquidID(_liquid_id);
_chunk->getWaterTile()->registerChunkLayer(this);
}
liquid_layer& liquid_layer::operator= (liquid_layer&& other)
@@ -390,6 +393,8 @@ void liquid_layer::changeLiquidID(int id)
catch (...)
{
}
registerUpdate(ll_TYPE);
}
void liquid_layer::update_indices()
@@ -564,6 +569,8 @@ void liquid_layer::crop(MapChunk* chunk)
}
}
registerUpdate(ll_HEIGHT);
update_min_max();
}
@@ -576,6 +583,8 @@ void liquid_layer::update_opacity(MapChunk* chunk, float factor)
update_vertex_opacity(x, z, chunk, factor);
}
}
registerUpdate(ll_DEPTH);
}
bool liquid_layer::hasSubchunk(int x, int z, int size) const
@@ -596,6 +605,7 @@ bool liquid_layer::hasSubchunk(int x, int z, int size) const
void liquid_layer::setSubchunk(int x, int z, bool water)
{
misc::set_bit(_subchunks, x, z, water);
registerUpdate(ll_HEIGHT);
}
void liquid_layer::paintLiquid( math::vector_3d const& cursor_pos
@@ -649,6 +659,8 @@ void liquid_layer::paintLiquid( math::vector_3d const& cursor_pos
id++;
}
registerUpdate(ll_HEIGHT || ll_DEPTH);
update_min_max();
}
@@ -695,12 +707,14 @@ void liquid_layer::copy_subchunk_height(int x, int z, liquid_layer const& from)
}
setSubchunk(x, z, true);
registerUpdate(ll_HEIGHT);
}
void liquid_layer::update_vertex_opacity(int x, int z, MapChunk* chunk, float factor)
{
float diff = _vertices[z * 9 + x].y - chunk->mVertices[z * 17 + x].y;
_depth[z * 9 + x] = diff < 0.0f ? 0.0f : (std::min(1.0f, std::max(0.0f, (diff + 1.0f) * factor)));
registerUpdate(ll_DEPTH);
}
int liquid_layer::get_lod_level(math::vector_3d const& camera_pos) const
@@ -720,7 +734,13 @@ void liquid_layer::set_lod_level(int lod_level)
_current_lod_indices_count = _indices_by_lod[lod_level].size();
}
void liquid_layer::registerUpdate(unsigned flags)
{
_update_flags |= flags;
_chunk->getWaterTile()->registerChunkLayerUpdate(flags);
}
liquid_layer::~liquid_layer()
{
_chunk->getWaterTile()->unregisterChunkLayer(this);
_update_flags = _update_flags;
}

View File

@@ -6,15 +6,25 @@
#include <noggit/MapHeaders.h>
#include <noggit/liquid_render.hpp>
#include <opengl/scoped.hpp>
#include <array>
class MapChunk;
class sExtendableArray;
class ChunkWater;
enum LiquidLayerUpdateFlags
{
ll_HEIGHT = 0x1,
ll_DEPTH = 0x2,
ll_UV = 0x4,
ll_TYPE = 0x8,
ll_FLAGS = 0x10
};
// handle liquids like oceans, lakes, rivers, slime, magma
class liquid_layer
{
public:
liquid_layer() = delete;
liquid_layer(ChunkWater* chunk, math::vector_3d const& base, float height, int liquid_id);
@@ -42,6 +52,9 @@ public:
void crop(MapChunk* chunk);
void update_opacity(MapChunk* chunk, float factor);
std::array<math::vector_3d, 9 * 9>& getVertices() { return _vertices; };
std::array<float, 9 * 9>& getDepth() { return _depth; };
std::array<math::vector_2d, 9 * 9>& getTexCoords() { return _tex_coords; };
float min() const { return _minimum; }
float max() const { return _maximum; }
@@ -50,6 +63,8 @@ public:
bool hasSubchunk(int x, int z, int size = 1) const;
void setSubchunk(int x, int z, bool water);
std::uint64_t getSubchunks() { return _subchunks; };
bool empty() const { return !_subchunks; }
bool full() const { return _subchunks == std::uint64_t(-1); }
void clear() { _subchunks = std::uint64_t(0); }
@@ -69,7 +84,9 @@ public:
void copy_subchunk_height(int x, int z, liquid_layer const& from);
void unload();
void registerUpdate(unsigned flags);
void doneUpdate() { _update_flags = 0; };
unsigned getUpdateFlags() { return _update_flags; };
ChunkWater* getChunk() { return _chunk; };
private:
@@ -95,10 +112,12 @@ private:
int _liquid_vertex_format;
float _minimum;
float _maximum;
std::uint64_t _subchunks;
std::vector<math::vector_3d> _vertices;
std::vector<float> _depth;
std::vector<math::vector_2d> _tex_coords;
std::array<math::vector_3d, 9 * 9> _vertices;
std::array<float, 9 * 9> _depth;
std::array<math::vector_2d, 9 * 9> _tex_coords;
std::map<int, std::vector<std::uint16_t>> _indices_by_lod;
bool _need_buffer_update = true;
@@ -112,4 +131,5 @@ private:
private:
math::vector_3d pos;
ChunkWater* _chunk;
unsigned _update_flags = ll_HEIGHT || ll_DEPTH || ll_UV || ll_FLAGS || ll_TYPE;;
};

View File

@@ -44,6 +44,8 @@ namespace noggit
_filename = texture;
_need_update = true;
update_texture_if_needed();
emit texture_updated();
}
void current_texture::update_texture_if_needed()

View File

@@ -42,6 +42,10 @@ namespace noggit
signals:
void texture_dropped(std::string const& filename);
void texture_updated();
public:
current_texture(bool accept_drop, QWidget* parent = nullptr);

View File

@@ -169,7 +169,14 @@ namespace noggit
if (file.open(QFile::ReadOnly))
{
QString style_sheet = QLatin1String(file.readAll());
qApp->setStyleSheet(style_sheet);;
QString style_sheet_fixed = style_sheet.replace("@rpath", QCoreApplication::applicationDirPath());
if (style_sheet_fixed.endsWith("/"))
style_sheet_fixed.chop(1);
else if (style_sheet_fixed.endsWith("\\"))
style_sheet_fixed.chop(2);
qApp->setStyleSheet(style_sheet_fixed);
}
}
);

View File

@@ -97,7 +97,7 @@ namespace noggit
_brush_level_slider->setRange (0, 255);
_brush_level_slider->setSliderPosition (_brush_level);
_brush_level_slider->setAccessibleName("texturing_brush_level_slider");
_brush_level_slider->setObjectName("texturing_brush_level_slider");
slider_layout_right->addWidget(_brush_level_slider, 0, Qt::AlignHCenter);

View File

@@ -207,6 +207,8 @@ namespace opengl
BOOST_FORCEINLINE void drawElements (GLenum mode, GLuint index_buffer, GLsizei count, GLenum type, GLvoid const* indices);
BOOST_FORCEINLINE void drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
QOpenGLContext* getCurrentContext();
BOOST_FORCEINLINE void bufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void* data);

View File

@@ -1058,4 +1058,13 @@ void opengl::context::drawElements (GLenum mode, GLuint index_buffer, GLsizei co
gl.bindBuffer (GL_ELEMENT_ARRAY_BUFFER, old);
}
void opengl::context::drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount)
{
#ifndef NOGGIT_DO_NOT_CHECK_FOR_OPENGL_ERRORS
verify_context_and_check_for_gl_errors const _ (_current_context, BOOST_CURRENT_FUNCTION);
#endif
return _4_1_core_func->glDrawArraysInstanced (mode, first, count, instancecount);
}
#endif //NOGGIT_CONTEXT_INL

View File

@@ -256,6 +256,14 @@ namespace opengl
gl.uniform1iv (loc, value.size(), value.data());
}
void use_program::uniform (std::string const& name, int const* data, std::size_t size)
{
GLuint loc = uniform_location (name);
if (loc < 0)
return;
gl.uniform1iv (loc, size, data);
}
void use_program::uniform (GLint pos, std::vector<int> const& value)
{
gl.uniform1iv (pos, value.size(), value.data());

View File

@@ -91,6 +91,7 @@ namespace opengl
void bind_uniform_block(std::string const& name, unsigned);
void uniform (std::string const& name, std::vector<int> const&);
void uniform (std::string const& name, int const* data, std::size_t size);
void uniform (GLint pos, std::vector<int> const&);
void uniform (std::string const& name, GLint);
void uniform (GLint pos, GLint);

View File

@@ -15,7 +15,8 @@ namespace opengl
MVP,
LIGHTING,
TERRAIN_OVERLAYS,
CHUNK_INSTANCE_DATA
CHUNK_INSTANCE_DATA,
CHUNK_LIQUID_INSTANCE_INDEX
};
struct MVPUniformBlock
@@ -47,9 +48,9 @@ namespace opengl
int wireframe_type;
float wireframe_radius;
float wireframe_width;
int draw_impass_overlay;
int draw_paintability_overlay;
int draw_selection_overlay;
int draw_impass_overlay = false;
int draw_paintability_overlay = false;
int draw_selection_overlay = false;
math::vector_4d wireframe_color;
};
@@ -66,10 +67,17 @@ namespace opengl
int ChunkTexAnimDir[4];
};
struct LiquidChunkInstanceDataUniformBlock
{
unsigned TextureArray_Pad3[4];
float ChunkXY_Animation[4];
};
struct LiquidChunkInstanceDataUniformBlock
{
unsigned texture_array;
unsigned type;
float xbase;
float zbase;
float anim_u;
float anim_v;
unsigned subchunks_1;
unsigned subchunks_2;
};
}