mirror of
https://github.com/doukutsu-rs/doukutsu-rs
synced 2025-04-06 03:44:26 +00:00
water improvements
This commit is contained in:
parent
d61602b7bb
commit
e216110864
|
@ -1,15 +1,18 @@
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use crate::common::{Color, Rect};
|
use crate::common::{Color, Rect};
|
||||||
use crate::entity::GameEntity;
|
use crate::entity::GameEntity;
|
||||||
use crate::frame::Frame;
|
use crate::frame::Frame;
|
||||||
use crate::framework::backend::{BackendShader, VertexData};
|
use crate::framework::backend::{BackendShader, SpriteBatchCommand, VertexData};
|
||||||
use crate::framework::context::Context;
|
use crate::framework::context::Context;
|
||||||
use crate::framework::error::GameResult;
|
use crate::framework::error::GameResult;
|
||||||
use crate::framework::graphics;
|
use crate::framework::graphics;
|
||||||
use crate::map::WaterRegionType;
|
use crate::graphics::BlendMode;
|
||||||
|
use crate::map::{WaterParamEntry, WaterParams, WaterRegionType};
|
||||||
|
use crate::npc::list::NPCList;
|
||||||
|
use crate::physics::PhysicalEntity;
|
||||||
use crate::player::Player;
|
use crate::player::Player;
|
||||||
use crate::shared_game_state::SharedGameState;
|
use crate::shared_game_state::SharedGameState;
|
||||||
use crate::physics::PhysicalEntity;
|
|
||||||
use crate::npc::list::NPCList;
|
|
||||||
|
|
||||||
const TENSION: f32 = 0.03;
|
const TENSION: f32 = 0.03;
|
||||||
const DAMPENING: f32 = 0.01;
|
const DAMPENING: f32 = 0.01;
|
||||||
|
@ -37,10 +40,11 @@ pub struct DynamicWater {
|
||||||
y: u16,
|
y: u16,
|
||||||
end_x: u16,
|
end_x: u16,
|
||||||
columns: Vec<DynamicWaterColumn>,
|
columns: Vec<DynamicWaterColumn>,
|
||||||
|
color: WaterParamEntry,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DynamicWater {
|
impl DynamicWater {
|
||||||
pub fn new(x: u16, y: u16, length: u16) -> DynamicWater {
|
pub fn new(x: u16, y: u16, length: u16, color: WaterParamEntry) -> DynamicWater {
|
||||||
let mut columns = Vec::new();
|
let mut columns = Vec::new();
|
||||||
let count = length as usize * 8 + 1;
|
let count = length as usize * 8 + 1;
|
||||||
|
|
||||||
|
@ -48,7 +52,7 @@ impl DynamicWater {
|
||||||
columns.push(DynamicWaterColumn::new());
|
columns.push(DynamicWaterColumn::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicWater { x, y, end_x: x + length, columns }
|
DynamicWater { x, y, end_x: x + length, columns, color }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tick(&mut self) {
|
pub fn tick(&mut self) {
|
||||||
|
@ -92,25 +96,26 @@ impl DynamicWater {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WaterRenderer {
|
pub struct WaterRenderer {
|
||||||
depth_regions: Vec<Rect<u16>>,
|
depth_regions: Vec<(Rect<u16>, WaterParamEntry)>,
|
||||||
surf_regions: Vec<Rect<u16>>,
|
|
||||||
water_surfaces: Vec<DynamicWater>,
|
water_surfaces: Vec<DynamicWater>,
|
||||||
|
t: RefCell<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WaterRenderer {
|
impl WaterRenderer {
|
||||||
pub fn new() -> WaterRenderer {
|
pub fn new() -> WaterRenderer {
|
||||||
WaterRenderer { depth_regions: Vec::new(), surf_regions: Vec::new(), water_surfaces: Vec::new() }
|
WaterRenderer { depth_regions: Vec::new(), water_surfaces: Vec::new(), t: RefCell::new(0.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initialize(&mut self, regions: Vec<(WaterRegionType, Rect<u16>)>) {
|
pub fn initialize(&mut self, regions: Vec<(WaterRegionType, Rect<u16>, u8)>, water_params: &WaterParams) {
|
||||||
for (reg_type, bounds) in regions {
|
for (reg_type, bounds, color_idx) in regions {
|
||||||
|
let color = water_params.get_entry(color_idx);
|
||||||
|
|
||||||
match reg_type {
|
match reg_type {
|
||||||
WaterRegionType::WaterLine => {
|
WaterRegionType::WaterLine => {
|
||||||
self.surf_regions.push(bounds);
|
self.water_surfaces.push(DynamicWater::new(bounds.left, bounds.top, bounds.width() + 1, *color));
|
||||||
self.water_surfaces.push(DynamicWater::new(bounds.left, bounds.top, bounds.width() + 1));
|
|
||||||
}
|
}
|
||||||
WaterRegionType::WaterDepth => {
|
WaterRegionType::WaterDepth => {
|
||||||
self.depth_regions.push(bounds);
|
self.depth_regions.push((bounds, *color));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,10 +124,6 @@ impl WaterRenderer {
|
||||||
|
|
||||||
impl GameEntity<(&[&Player], &NPCList)> for WaterRenderer {
|
impl GameEntity<(&[&Player], &NPCList)> for WaterRenderer {
|
||||||
fn tick(&mut self, state: &mut SharedGameState, (players, npc_list): (&[&Player], &NPCList)) -> GameResult<()> {
|
fn tick(&mut self, state: &mut SharedGameState, (players, npc_list): (&[&Player], &NPCList)) -> GameResult<()> {
|
||||||
if !state.settings.shader_effects {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
for surf in &mut self.water_surfaces {
|
for surf in &mut self.water_surfaces {
|
||||||
let line_x = surf.x as f32 * 16.0;
|
let line_x = surf.x as f32 * 16.0;
|
||||||
let line_y = surf.y as f32 * 16.0;
|
let line_y = surf.y as f32 * 16.0;
|
||||||
|
@ -169,39 +170,48 @@ impl GameEntity<(&[&Player], &NPCList)> for WaterRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw(&self, state: &mut SharedGameState, ctx: &mut Context, frame: &Frame) -> GameResult<()> {
|
fn draw(&self, state: &mut SharedGameState, ctx: &mut Context, frame: &Frame) -> GameResult<()> {
|
||||||
let mut out_rect = Rect::new(0, 0, 0, 0);
|
if !graphics::supports_vertex_draw(ctx)? {
|
||||||
let (o_x, o_y) = frame.xy_interpolated(state.frame_time);
|
|
||||||
let water_color_top = Color::from_rgba(102, 153, 204, 150);
|
|
||||||
let water_color = Color::from_rgba(102, 153, 204, 75);
|
|
||||||
|
|
||||||
for region in &self.depth_regions {
|
|
||||||
out_rect.left = ((region.left as f32 * 16.0 - o_x - 8.0) * state.scale) as isize;
|
|
||||||
out_rect.top = ((region.top as f32 * 16.0 - o_y - 8.0) * state.scale) as isize;
|
|
||||||
out_rect.right = ((region.right as f32 * 16.0 - o_x + 8.0) * state.scale) as isize;
|
|
||||||
out_rect.bottom = ((region.bottom as f32 * 16.0 - o_y + 8.0) * state.scale) as isize;
|
|
||||||
graphics::draw_rect(ctx, out_rect, water_color)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if !state.settings.shader_effects || !graphics::supports_vertex_draw(ctx)? {
|
|
||||||
for region in &self.surf_regions {
|
|
||||||
out_rect.left = ((region.left as f32 * 16.0 - o_x - 8.0) * state.scale) as isize;
|
|
||||||
out_rect.top = ((region.top as f32 * 16.0 - o_y - 5.0) * state.scale) as isize;
|
|
||||||
out_rect.right = ((region.right as f32 * 16.0 - o_x + 8.0) * state.scale) as isize;
|
|
||||||
out_rect.bottom = ((region.bottom as f32 * 16.0 - o_y + 8.0) * state.scale) as isize;
|
|
||||||
graphics::draw_rect(ctx, out_rect, water_color)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let uv = (0.0, 0.0);
|
graphics::set_render_target(ctx, state.lightmap_canvas.as_ref())?;
|
||||||
let color_top_rgba = water_color_top.to_rgba();
|
graphics::clear(ctx, Color::from_rgba(0, 0, 0, 0));
|
||||||
let color_mid_rgba = water_color.to_rgba();
|
graphics::set_blend_mode(ctx, BlendMode::None)?;
|
||||||
let color_btm_rgba = water_color.to_rgba();
|
|
||||||
|
let (o_x, o_y) = frame.xy_interpolated(state.frame_time);
|
||||||
|
let uv = (0.5, 0.5);
|
||||||
|
let mut t_ref = self.t.borrow_mut();
|
||||||
|
let t = *t_ref;
|
||||||
|
*t_ref += state.frame_time as f32;
|
||||||
|
let shader = BackendShader::WaterFill(state.scale, t, (o_x, o_y));
|
||||||
|
|
||||||
|
for (region, color) in &self.depth_regions {
|
||||||
|
let color_mid_rgba = color.color_middle.to_rgba();
|
||||||
|
let color_btm_rgba = color.color_bottom.to_rgba();
|
||||||
|
let mut vertices = vec![];
|
||||||
|
vertices.reserve(6);
|
||||||
|
|
||||||
|
let left = (region.left as f32 * 16.0 - o_x - 8.0) * state.scale;
|
||||||
|
let top = (region.top as f32 * 16.0 - o_y - 8.0) * state.scale;
|
||||||
|
let right = (region.right as f32 * 16.0 - o_x + 8.0) * state.scale;
|
||||||
|
let bottom = (region.bottom as f32 * 16.0 - o_y + 8.0) * state.scale;
|
||||||
|
|
||||||
|
vertices.push(VertexData { position: (left, bottom), uv, color: color_btm_rgba });
|
||||||
|
vertices.push(VertexData { position: (left, top), uv, color: color_mid_rgba });
|
||||||
|
vertices.push(VertexData { position: (right, top), uv, color: color_mid_rgba });
|
||||||
|
vertices.push(VertexData { position: (left, bottom), uv, color: color_btm_rgba });
|
||||||
|
vertices.push(VertexData { position: (right, top), uv, color: color_mid_rgba });
|
||||||
|
vertices.push(VertexData { position: (right, bottom), uv, color: color_btm_rgba });
|
||||||
|
|
||||||
|
graphics::draw_triangle_list(ctx, vertices, None, shader)?;
|
||||||
|
}
|
||||||
|
|
||||||
for surf in &self.water_surfaces {
|
for surf in &self.water_surfaces {
|
||||||
let pos_x = surf.x as f32 * 16.0;
|
let pos_x = surf.x as f32 * 16.0;
|
||||||
let pos_y = surf.y as f32 * 16.0;
|
let pos_y = surf.y as f32 * 16.0;
|
||||||
|
let color_top_rgba = surf.color.color_top.to_rgba();
|
||||||
|
let color_mid_rgba = surf.color.color_middle.to_rgba();
|
||||||
|
let color_btm_rgba = surf.color.color_bottom.to_rgba();
|
||||||
|
|
||||||
if (pos_x - o_x - 16.0) > state.canvas_size.0
|
if (pos_x - o_x - 16.0) > state.canvas_size.0
|
||||||
|| (pos_x - o_x + 16.0 + surf.end_x as f32 * 16.0) < 0.0
|
|| (pos_x - o_x + 16.0 + surf.end_x as f32 * 16.0) < 0.0
|
||||||
|
@ -238,7 +248,19 @@ impl GameEntity<(&[&Player], &NPCList)> for WaterRenderer {
|
||||||
vertices.push(VertexData { position: (x_right, bottom), uv, color: color_btm_rgba });
|
vertices.push(VertexData { position: (x_right, bottom), uv, color: color_btm_rgba });
|
||||||
}
|
}
|
||||||
|
|
||||||
graphics::draw_triangle_list(ctx, vertices, None, BackendShader::Fill)?;
|
graphics::draw_triangle_list(ctx, vertices, None, shader)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
graphics::set_blend_mode(ctx, BlendMode::Alpha)?;
|
||||||
|
graphics::set_render_target(ctx, None)?;
|
||||||
|
|
||||||
|
{
|
||||||
|
let canvas = state.lightmap_canvas.as_mut().unwrap();
|
||||||
|
let rect = Rect { left: 0.0, top: 0.0, right: state.screen_size.0, bottom: state.screen_size.1 };
|
||||||
|
|
||||||
|
canvas.clear();
|
||||||
|
canvas.add(SpriteBatchCommand::DrawRect(rect, rect));
|
||||||
|
canvas.draw()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -17,6 +17,8 @@ pub struct VertexData {
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
pub enum BackendShader {
|
pub enum BackendShader {
|
||||||
|
/// (scale, t, (frame_x, frame_y))
|
||||||
|
WaterFill(f32, f32, (f32, f32)),
|
||||||
Fill,
|
Fill,
|
||||||
Texture,
|
Texture,
|
||||||
}
|
}
|
||||||
|
|
|
@ -538,6 +538,7 @@ impl BackendRenderer for SDL2Renderer {
|
||||||
BlendMode::Add => sdl2::render::BlendMode::Add,
|
BlendMode::Add => sdl2::render::BlendMode::Add,
|
||||||
BlendMode::Alpha => sdl2::render::BlendMode::Blend,
|
BlendMode::Alpha => sdl2::render::BlendMode::Blend,
|
||||||
BlendMode::Multiply => sdl2::render::BlendMode::Mod,
|
BlendMode::Multiply => sdl2::render::BlendMode::Mod,
|
||||||
|
BlendMode::None => sdl2::render::BlendMode::None,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -738,6 +739,8 @@ impl BackendRenderer for SDL2Renderer {
|
||||||
let mut refs = self.refs.borrow_mut();
|
let mut refs = self.refs.borrow_mut();
|
||||||
if shader == BackendShader::Fill {
|
if shader == BackendShader::Fill {
|
||||||
texture = None;
|
texture = None;
|
||||||
|
} else if let BackendShader::WaterFill(..) = shader {
|
||||||
|
texture = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let texture_ptr = if let Some(texture) = texture {
|
let texture_ptr = if let Some(texture) = texture {
|
||||||
|
|
|
@ -10,6 +10,7 @@ pub enum FilterMode {
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum BlendMode {
|
pub enum BlendMode {
|
||||||
|
None,
|
||||||
/// When combining two fragments, add their values together, saturating
|
/// When combining two fragments, add their values together, saturating
|
||||||
/// at 1.0
|
/// at 1.0
|
||||||
Add,
|
Add,
|
||||||
|
|
|
@ -16,6 +16,7 @@ use crate::framework::gl;
|
||||||
use crate::framework::gl::types::*;
|
use crate::framework::gl::types::*;
|
||||||
use crate::framework::graphics::BlendMode;
|
use crate::framework::graphics::BlendMode;
|
||||||
use crate::framework::util::{field_offset, return_param};
|
use crate::framework::util::{field_offset, return_param};
|
||||||
|
use crate::GameError;
|
||||||
|
|
||||||
pub struct GLContext {
|
pub struct GLContext {
|
||||||
pub gles2_mode: bool,
|
pub gles2_mode: bool,
|
||||||
|
@ -29,8 +30,7 @@ pub struct OpenGLTexture {
|
||||||
height: u16,
|
height: u16,
|
||||||
texture_id: u32,
|
texture_id: u32,
|
||||||
framebuffer_id: u32,
|
framebuffer_id: u32,
|
||||||
locs: Locs,
|
shader: RenderShader,
|
||||||
program: GLuint,
|
|
||||||
vbo: GLuint,
|
vbo: GLuint,
|
||||||
vertices: Vec<VertexData>,
|
vertices: Vec<VertexData>,
|
||||||
context_active: Arc<RefCell<bool>>,
|
context_active: Arc<RefCell<bool>>,
|
||||||
|
@ -181,41 +181,9 @@ impl BackendTexture for OpenGLTexture {
|
||||||
gl.gl.Enable(gl::BLEND);
|
gl.gl.Enable(gl::BLEND);
|
||||||
gl.gl.Disable(gl::DEPTH_TEST);
|
gl.gl.Disable(gl::DEPTH_TEST);
|
||||||
|
|
||||||
|
self.shader.bind_attrib_pointer(gl, self.vbo);
|
||||||
|
|
||||||
gl.gl.BindTexture(gl::TEXTURE_2D, self.texture_id);
|
gl.gl.BindTexture(gl::TEXTURE_2D, self.texture_id);
|
||||||
gl.gl.BindBuffer(gl::ARRAY_BUFFER, self.vbo);
|
|
||||||
gl.gl.UseProgram(self.program);
|
|
||||||
gl.gl.EnableVertexAttribArray(self.locs.position);
|
|
||||||
gl.gl.EnableVertexAttribArray(self.locs.uv);
|
|
||||||
gl.gl.EnableVertexAttribArray(self.locs.color);
|
|
||||||
|
|
||||||
gl.gl.VertexAttribPointer(
|
|
||||||
self.locs.position,
|
|
||||||
2,
|
|
||||||
gl::FLOAT,
|
|
||||||
gl::FALSE,
|
|
||||||
mem::size_of::<VertexData>() as _,
|
|
||||||
field_offset::<VertexData, _, _>(|v| &v.position) as _,
|
|
||||||
);
|
|
||||||
|
|
||||||
gl.gl.VertexAttribPointer(
|
|
||||||
self.locs.uv,
|
|
||||||
2,
|
|
||||||
gl::FLOAT,
|
|
||||||
gl::FALSE,
|
|
||||||
mem::size_of::<VertexData>() as _,
|
|
||||||
field_offset::<VertexData, _, _>(|v| &v.uv) as _,
|
|
||||||
);
|
|
||||||
|
|
||||||
gl.gl.VertexAttribPointer(
|
|
||||||
self.locs.color,
|
|
||||||
4,
|
|
||||||
gl::UNSIGNED_BYTE,
|
|
||||||
gl::TRUE,
|
|
||||||
mem::size_of::<VertexData>() as _,
|
|
||||||
field_offset::<VertexData, _, _>(|v| &v.color) as _,
|
|
||||||
);
|
|
||||||
|
|
||||||
gl.gl.BindBuffer(gl::ARRAY_BUFFER, self.vbo);
|
|
||||||
gl.gl.BufferData(
|
gl.gl.BufferData(
|
||||||
gl::ARRAY_BUFFER,
|
gl::ARRAY_BUFFER,
|
||||||
(self.vertices.len() * mem::size_of::<VertexData>()) as _,
|
(self.vertices.len() * mem::size_of::<VertexData>()) as _,
|
||||||
|
@ -257,7 +225,7 @@ impl Drop for OpenGLTexture {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_shader_compile_status(shader: u32, gl: &Gl) -> bool {
|
fn check_shader_compile_status(shader: u32, gl: &Gl) -> GameResult {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut status: GLint = 0;
|
let mut status: GLint = 0;
|
||||||
gl.gl.GetShaderiv(shader, gl::COMPILE_STATUS, (&mut status) as *mut _);
|
gl.gl.GetShaderiv(shader, gl::COMPILE_STATUS, (&mut status) as *mut _);
|
||||||
|
@ -276,13 +244,11 @@ fn check_shader_compile_status(shader: u32, gl: &Gl) -> bool {
|
||||||
);
|
);
|
||||||
|
|
||||||
let data = String::from_utf8_lossy(&data);
|
let data = String::from_utf8_lossy(&data);
|
||||||
log::error!("Failed to compile shader {}: {}", shader, data);
|
return Err(GameError::RenderError(format!("Failed to compile shader {}: {}", shader, data)));
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
const VERTEX_SHADER_BASIC: &str = r"
|
const VERTEX_SHADER_BASIC: &str = r"
|
||||||
|
@ -331,6 +297,51 @@ void main()
|
||||||
|
|
||||||
";
|
";
|
||||||
|
|
||||||
|
const FRAGMENT_SHADER_WATER: &str = r"
|
||||||
|
#version 110
|
||||||
|
|
||||||
|
uniform mat4 ProjMtx;
|
||||||
|
uniform sampler2D Texture;
|
||||||
|
uniform float Time;
|
||||||
|
uniform float Scale;
|
||||||
|
uniform vec2 FrameOffset;
|
||||||
|
varying vec4 Frag_Color;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 resolution_inv = vec2(ProjMtx[0][0], -ProjMtx[1][1]) * 0.5;
|
||||||
|
vec2 uv = gl_FragCoord.xy * resolution_inv;
|
||||||
|
vec2 wave = uv;
|
||||||
|
wave.x += sin((-FrameOffset.y * resolution_inv.y + uv.x * 16.0) + Time / 20.0) * Scale * resolution_inv.x;
|
||||||
|
wave.y -= cos((-FrameOffset.x * resolution_inv.x + uv.y * 16.0) + Time / 5.0) * Scale * resolution_inv.y;
|
||||||
|
float off = 0.35 * Scale * resolution_inv.y;
|
||||||
|
float off2 = 2.0 * off;
|
||||||
|
|
||||||
|
vec3 color = texture2D(Texture, wave).rgb * 0.25;
|
||||||
|
color += texture2D(Texture, wave + vec2(0, off)).rgb * 0.125;
|
||||||
|
color += texture2D(Texture, wave + vec2(0, -off)).rgb * 0.125;
|
||||||
|
|
||||||
|
color.rg += texture2D(Texture, wave + vec2(-off, -off)).rg * 0.0625;
|
||||||
|
color.rg += texture2D(Texture, wave + vec2(-off, 0)).rg * 0.125;
|
||||||
|
color.rg += texture2D(Texture, wave + vec2(-off, off)).rg * 0.0625;
|
||||||
|
color.b += texture2D(Texture, wave + vec2(-off2, -off)).b * 0.0625;
|
||||||
|
color.b += texture2D(Texture, wave + vec2(-off2, 0)).b * 0.125;
|
||||||
|
color.b += texture2D(Texture, wave + vec2(-off2, off)).b * 0.0625;
|
||||||
|
|
||||||
|
color.rg += texture2D(Texture, wave + vec2(off, off)).gb * 0.0625;
|
||||||
|
color.rg += texture2D(Texture, wave + vec2(off, 0)).gb * 0.125;
|
||||||
|
color.rg += texture2D(Texture, wave + vec2(off, -off)).gb * 0.0625;
|
||||||
|
color.b += texture2D(Texture, wave + vec2(off2, off)).r * 0.0625;
|
||||||
|
color.b += texture2D(Texture, wave + vec2(off2, 0)).r * 0.125;
|
||||||
|
color.b += texture2D(Texture, wave + vec2(off2, -off)).r * 0.0625;
|
||||||
|
|
||||||
|
color *= (1.0 - Frag_Color.a);
|
||||||
|
color += Frag_Color.rgb * Frag_Color.a;
|
||||||
|
gl_FragColor = vec4(color, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
";
|
||||||
|
|
||||||
const VERTEX_SHADER_BASIC_GLES: &str = r"
|
const VERTEX_SHADER_BASIC_GLES: &str = r"
|
||||||
#version 100
|
#version 100
|
||||||
|
|
||||||
|
@ -384,20 +395,131 @@ void main()
|
||||||
";
|
";
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
struct Locs {
|
struct RenderShader {
|
||||||
|
program_id: GLuint,
|
||||||
texture: GLint,
|
texture: GLint,
|
||||||
proj_mtx: GLint,
|
proj_mtx: GLint,
|
||||||
|
scale: GLint,
|
||||||
|
time: GLint,
|
||||||
|
frame_offset: GLint,
|
||||||
position: GLuint,
|
position: GLuint,
|
||||||
uv: GLuint,
|
uv: GLuint,
|
||||||
color: GLuint,
|
color: GLuint,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ImguiData {
|
impl Default for RenderShader {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { program_id: 0, texture: 0, proj_mtx: 0, scale: 0, time: 0, frame_offset: 0, position: 0, uv: 0, color: 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RenderShader {
|
||||||
|
fn compile(gl: &Gl, vertex_shader: &str, fragment_shader: &str) -> GameResult<RenderShader> {
|
||||||
|
let mut shader = RenderShader::default();
|
||||||
|
unsafe {
|
||||||
|
shader.program_id = gl.gl.CreateProgram();
|
||||||
|
|
||||||
|
unsafe fn cleanup(shader: &mut RenderShader, gl: &Gl, vert: GLuint, frag: GLuint) {
|
||||||
|
if vert != 0 {
|
||||||
|
gl.gl.DeleteShader(vert);
|
||||||
|
}
|
||||||
|
|
||||||
|
if frag != 0 {
|
||||||
|
gl.gl.DeleteShader(frag);
|
||||||
|
}
|
||||||
|
|
||||||
|
if shader.program_id != 0 {
|
||||||
|
gl.gl.DeleteProgram(shader.program_id);
|
||||||
|
shader.program_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*shader = RenderShader::default();
|
||||||
|
}
|
||||||
|
|
||||||
|
let vert_shader = gl.gl.CreateShader(gl::VERTEX_SHADER);
|
||||||
|
let frag_shader = gl.gl.CreateShader(gl::FRAGMENT_SHADER);
|
||||||
|
|
||||||
|
let vert_sources = [vertex_shader.as_ptr() as *const GLchar];
|
||||||
|
let frag_sources = [fragment_shader.as_ptr() as *const GLchar];
|
||||||
|
let vert_sources_len = [vertex_shader.len() as GLint - 1];
|
||||||
|
let frag_sources_len = [fragment_shader.len() as GLint - 1];
|
||||||
|
|
||||||
|
gl.gl.ShaderSource(vert_shader, 1, vert_sources.as_ptr(), vert_sources_len.as_ptr());
|
||||||
|
gl.gl.ShaderSource(frag_shader, 1, frag_sources.as_ptr(), frag_sources_len.as_ptr());
|
||||||
|
|
||||||
|
gl.gl.CompileShader(vert_shader);
|
||||||
|
gl.gl.CompileShader(frag_shader);
|
||||||
|
|
||||||
|
if let Err(e) = check_shader_compile_status(vert_shader, gl) {
|
||||||
|
cleanup(&mut shader, gl, vert_shader, frag_shader);
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(e) = check_shader_compile_status(frag_shader, gl) {
|
||||||
|
cleanup(&mut shader, gl, vert_shader, frag_shader);
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
gl.gl.AttachShader(shader.program_id, vert_shader);
|
||||||
|
gl.gl.AttachShader(shader.program_id, frag_shader);
|
||||||
|
gl.gl.LinkProgram(shader.program_id);
|
||||||
|
|
||||||
|
shader.texture = gl.gl.GetUniformLocation(shader.program_id, b"Texture\0".as_ptr() as _);
|
||||||
|
shader.proj_mtx = gl.gl.GetUniformLocation(shader.program_id, b"ProjMtx\0".as_ptr() as _);
|
||||||
|
shader.scale = gl.gl.GetUniformLocation(shader.program_id, b"Scale\0".as_ptr() as _) as _;
|
||||||
|
shader.time = gl.gl.GetUniformLocation(shader.program_id, b"Time\0".as_ptr() as _) as _;
|
||||||
|
shader.frame_offset = gl.gl.GetUniformLocation(shader.program_id, b"FrameOffset\0".as_ptr() as _) as _;
|
||||||
|
shader.position = gl.gl.GetAttribLocation(shader.program_id, b"Position\0".as_ptr() as _) as _;
|
||||||
|
shader.uv = gl.gl.GetAttribLocation(shader.program_id, b"UV\0".as_ptr() as _) as _;
|
||||||
|
shader.color = gl.gl.GetAttribLocation(shader.program_id, b"Color\0".as_ptr() as _) as _;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(shader)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn bind_attrib_pointer(&self, gl: &Gl, vbo: GLuint) -> GameResult {
|
||||||
|
gl.gl.UseProgram(self.program_id);
|
||||||
|
gl.gl.BindBuffer(gl::ARRAY_BUFFER, vbo);
|
||||||
|
gl.gl.EnableVertexAttribArray(self.position);
|
||||||
|
gl.gl.EnableVertexAttribArray(self.uv);
|
||||||
|
gl.gl.EnableVertexAttribArray(self.color);
|
||||||
|
|
||||||
|
gl.gl.VertexAttribPointer(
|
||||||
|
self.position,
|
||||||
|
2,
|
||||||
|
gl::FLOAT,
|
||||||
|
gl::FALSE,
|
||||||
|
mem::size_of::<VertexData>() as _,
|
||||||
|
field_offset::<VertexData, _, _>(|v| &v.position) as _,
|
||||||
|
);
|
||||||
|
|
||||||
|
gl.gl.VertexAttribPointer(
|
||||||
|
self.uv,
|
||||||
|
2,
|
||||||
|
gl::FLOAT,
|
||||||
|
gl::FALSE,
|
||||||
|
mem::size_of::<VertexData>() as _,
|
||||||
|
field_offset::<VertexData, _, _>(|v| &v.uv) as _,
|
||||||
|
);
|
||||||
|
|
||||||
|
gl.gl.VertexAttribPointer(
|
||||||
|
self.color,
|
||||||
|
4,
|
||||||
|
gl::UNSIGNED_BYTE,
|
||||||
|
gl::TRUE,
|
||||||
|
mem::size_of::<VertexData>() as _,
|
||||||
|
field_offset::<VertexData, _, _>(|v| &v.color) as _,
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RenderData {
|
||||||
initialized: bool,
|
initialized: bool,
|
||||||
program_tex: GLuint,
|
tex_shader: RenderShader,
|
||||||
program_fill: GLuint,
|
fill_shader: RenderShader,
|
||||||
tex_locs: Locs,
|
fill_water_shader: RenderShader,
|
||||||
fill_locs: Locs,
|
|
||||||
vbo: GLuint,
|
vbo: GLuint,
|
||||||
ebo: GLuint,
|
ebo: GLuint,
|
||||||
font_texture: GLuint,
|
font_texture: GLuint,
|
||||||
|
@ -407,14 +529,13 @@ struct ImguiData {
|
||||||
last_size: (u32, u32),
|
last_size: (u32, u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImguiData {
|
impl RenderData {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
ImguiData {
|
RenderData {
|
||||||
initialized: false,
|
initialized: false,
|
||||||
program_tex: 0,
|
tex_shader: RenderShader::default(),
|
||||||
program_fill: 0,
|
fill_shader: RenderShader::default(),
|
||||||
tex_locs: Locs { texture: 0, proj_mtx: 0, position: 0, uv: 0, color: 0 },
|
fill_water_shader: RenderShader::default(),
|
||||||
fill_locs: Locs { texture: 0, proj_mtx: 0, position: 0, uv: 0, color: 0 },
|
|
||||||
vbo: 0,
|
vbo: 0,
|
||||||
ebo: 0,
|
ebo: 0,
|
||||||
font_texture: 0,
|
font_texture: 0,
|
||||||
|
@ -431,76 +552,23 @@ impl ImguiData {
|
||||||
let vshdr_basic = if gles2_mode { VERTEX_SHADER_BASIC_GLES } else { VERTEX_SHADER_BASIC };
|
let vshdr_basic = if gles2_mode { VERTEX_SHADER_BASIC_GLES } else { VERTEX_SHADER_BASIC };
|
||||||
let fshdr_tex = if gles2_mode { FRAGMENT_SHADER_TEXTURED_GLES } else { FRAGMENT_SHADER_TEXTURED };
|
let fshdr_tex = if gles2_mode { FRAGMENT_SHADER_TEXTURED_GLES } else { FRAGMENT_SHADER_TEXTURED };
|
||||||
let fshdr_fill = if gles2_mode { FRAGMENT_SHADER_COLOR_GLES } else { FRAGMENT_SHADER_COLOR };
|
let fshdr_fill = if gles2_mode { FRAGMENT_SHADER_COLOR_GLES } else { FRAGMENT_SHADER_COLOR };
|
||||||
|
let fshdr_fill_water = if gles2_mode { FRAGMENT_SHADER_COLOR_GLES } else { FRAGMENT_SHADER_WATER };
|
||||||
let vert_sources = [vshdr_basic.as_ptr() as *const GLchar];
|
|
||||||
let frag_sources_tex = [fshdr_tex.as_ptr() as *const GLchar];
|
|
||||||
let frag_sources_fill = [fshdr_fill.as_ptr() as *const GLchar];
|
|
||||||
let vert_sources_len = [vshdr_basic.len() as GLint - 1];
|
|
||||||
let frag_sources_tex_len = [fshdr_tex.len() as GLint - 1];
|
|
||||||
let frag_sources_fill_len = [fshdr_fill.len() as GLint - 1];
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
self.program_tex = gl.gl.CreateProgram();
|
self.tex_shader =
|
||||||
self.program_fill = gl.gl.CreateProgram();
|
RenderShader::compile(gl, vshdr_basic, fshdr_tex).unwrap_or_else(|_| RenderShader::default());
|
||||||
let vert_shader = gl.gl.CreateShader(gl::VERTEX_SHADER);
|
self.fill_shader =
|
||||||
let frag_shader_tex = gl.gl.CreateShader(gl::FRAGMENT_SHADER);
|
RenderShader::compile(gl, vshdr_basic, fshdr_fill).unwrap_or_else(|_| RenderShader::default());
|
||||||
let frag_shader_fill = gl.gl.CreateShader(gl::FRAGMENT_SHADER);
|
self.fill_water_shader =
|
||||||
|
RenderShader::compile(gl, vshdr_basic, fshdr_fill_water).unwrap_or_else(|_| RenderShader::default());
|
||||||
gl.gl.ShaderSource(vert_shader, 1, vert_sources.as_ptr(), vert_sources_len.as_ptr());
|
|
||||||
gl.gl.ShaderSource(frag_shader_tex, 1, frag_sources_tex.as_ptr(), frag_sources_tex_len.as_ptr());
|
|
||||||
gl.gl.ShaderSource(frag_shader_fill, 1, frag_sources_fill.as_ptr(), frag_sources_fill_len.as_ptr());
|
|
||||||
|
|
||||||
gl.gl.CompileShader(vert_shader);
|
|
||||||
gl.gl.CompileShader(frag_shader_tex);
|
|
||||||
gl.gl.CompileShader(frag_shader_fill);
|
|
||||||
|
|
||||||
if !check_shader_compile_status(vert_shader, gl) {
|
|
||||||
gl.gl.DeleteShader(vert_shader);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !check_shader_compile_status(frag_shader_tex, gl) {
|
|
||||||
gl.gl.DeleteShader(frag_shader_tex);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !check_shader_compile_status(frag_shader_fill, gl) {
|
|
||||||
gl.gl.DeleteShader(frag_shader_fill);
|
|
||||||
}
|
|
||||||
|
|
||||||
gl.gl.AttachShader(self.program_tex, vert_shader);
|
|
||||||
gl.gl.AttachShader(self.program_tex, frag_shader_tex);
|
|
||||||
gl.gl.LinkProgram(self.program_tex);
|
|
||||||
|
|
||||||
gl.gl.AttachShader(self.program_fill, vert_shader);
|
|
||||||
gl.gl.AttachShader(self.program_fill, frag_shader_fill);
|
|
||||||
gl.gl.LinkProgram(self.program_fill);
|
|
||||||
|
|
||||||
self.tex_locs = Locs {
|
|
||||||
texture: gl.gl.GetUniformLocation(self.program_tex, b"Texture\0".as_ptr() as _),
|
|
||||||
proj_mtx: gl.gl.GetUniformLocation(self.program_tex, b"ProjMtx\0".as_ptr() as _),
|
|
||||||
position: gl.gl.GetAttribLocation(self.program_tex, b"Position\0".as_ptr() as _) as _,
|
|
||||||
uv: gl.gl.GetAttribLocation(self.program_tex, b"UV\0".as_ptr() as _) as _,
|
|
||||||
color: gl.gl.GetAttribLocation(self.program_tex, b"Color\0".as_ptr() as _) as _,
|
|
||||||
};
|
|
||||||
|
|
||||||
self.fill_locs = Locs {
|
|
||||||
texture: gl.gl.GetUniformLocation(self.program_fill, b"Texture\0".as_ptr() as _),
|
|
||||||
proj_mtx: gl.gl.GetUniformLocation(self.program_fill, b"ProjMtx\0".as_ptr() as _),
|
|
||||||
position: gl.gl.GetAttribLocation(self.program_fill, b"Position\0".as_ptr() as _) as _,
|
|
||||||
uv: gl.gl.GetAttribLocation(self.program_fill, b"UV\0".as_ptr() as _) as _,
|
|
||||||
color: gl.gl.GetAttribLocation(self.program_fill, b"Color\0".as_ptr() as _) as _,
|
|
||||||
};
|
|
||||||
|
|
||||||
self.vbo = return_param(|x| gl.gl.GenBuffers(1, x));
|
self.vbo = return_param(|x| gl.gl.GenBuffers(1, x));
|
||||||
self.ebo = return_param(|x| gl.gl.GenBuffers(1, x));
|
self.ebo = return_param(|x| gl.gl.GenBuffers(1, x));
|
||||||
|
|
||||||
let mut current_texture = 0;
|
|
||||||
gl.gl.GetIntegerv(gl::TEXTURE_BINDING_2D, &mut current_texture);
|
|
||||||
|
|
||||||
self.font_texture = return_param(|x| gl.gl.GenTextures(1, x));
|
self.font_texture = return_param(|x| gl.gl.GenTextures(1, x));
|
||||||
gl.gl.BindTexture(gl::TEXTURE_2D, self.font_texture);
|
gl.gl.BindTexture(gl::TEXTURE_2D, self.font_texture);
|
||||||
gl.gl.TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as _);
|
gl.gl.TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as _);
|
||||||
gl.gl.TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as _);
|
gl.gl.TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as _);
|
||||||
//gl.gl.PixelStorei(gl::UNPACK_ROW_LENGTH, 0);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut atlas = imgui.fonts();
|
let mut atlas = imgui.fonts();
|
||||||
|
@ -591,7 +659,7 @@ pub fn load_gl(gl_context: &mut GLContext) -> &'static Gl {
|
||||||
pub struct OpenGLRenderer {
|
pub struct OpenGLRenderer {
|
||||||
refs: GLContext,
|
refs: GLContext,
|
||||||
imgui: UnsafeCell<imgui::Context>,
|
imgui: UnsafeCell<imgui::Context>,
|
||||||
imgui_data: ImguiData,
|
render_data: RenderData,
|
||||||
context_active: Arc<RefCell<bool>>,
|
context_active: Arc<RefCell<bool>>,
|
||||||
def_matrix: [[f32; 4]; 4],
|
def_matrix: [[f32; 4]; 4],
|
||||||
curr_matrix: [[f32; 4]; 4],
|
curr_matrix: [[f32; 4]; 4],
|
||||||
|
@ -602,7 +670,7 @@ impl OpenGLRenderer {
|
||||||
OpenGLRenderer {
|
OpenGLRenderer {
|
||||||
refs,
|
refs,
|
||||||
imgui,
|
imgui,
|
||||||
imgui_data: ImguiData::new(),
|
render_data: RenderData::new(),
|
||||||
context_active: Arc::new(RefCell::new(true)),
|
context_active: Arc::new(RefCell::new(true)),
|
||||||
def_matrix: [[0.0; 4]; 4],
|
def_matrix: [[0.0; 4]; 4],
|
||||||
curr_matrix: [[0.0; 4]; 4],
|
curr_matrix: [[0.0; 4]; 4],
|
||||||
|
@ -615,8 +683,8 @@ impl OpenGLRenderer {
|
||||||
let gles2 = self.refs.gles2_mode;
|
let gles2 = self.refs.gles2_mode;
|
||||||
let gl = load_gl(&mut self.refs);
|
let gl = load_gl(&mut self.refs);
|
||||||
|
|
||||||
if !self.imgui_data.initialized {
|
if !self.render_data.initialized {
|
||||||
self.imgui_data.init(gles2, imgui, gl);
|
self.render_data.init(gles2, imgui, gl);
|
||||||
}
|
}
|
||||||
|
|
||||||
Some((&mut self.refs, gl))
|
Some((&mut self.refs, gl))
|
||||||
|
@ -649,8 +717,6 @@ impl BackendRenderer for OpenGLRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let ImguiData { program_tex, surf_texture, tex_locs: Locs { proj_mtx, .. }, .. } = self.imgui_data;
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if let Some((_, gl)) = self.get_context() {
|
if let Some((_, gl)) = self.get_context() {
|
||||||
gl.gl.BindFramebuffer(gl::FRAMEBUFFER, 0);
|
gl.gl.BindFramebuffer(gl::FRAMEBUFFER, 0);
|
||||||
|
@ -660,8 +726,8 @@ impl BackendRenderer for OpenGLRenderer {
|
||||||
let matrix =
|
let matrix =
|
||||||
[[2.0f32, 0.0, 0.0, 0.0], [0.0, -2.0, 0.0, 0.0], [0.0, 0.0, -1.0, 0.0], [-1.0, 1.0, 0.0, 1.0]];
|
[[2.0f32, 0.0, 0.0, 0.0], [0.0, -2.0, 0.0, 0.0], [0.0, 0.0, -1.0, 0.0], [-1.0, 1.0, 0.0, 1.0]];
|
||||||
|
|
||||||
gl.gl.UseProgram(program_tex);
|
self.render_data.tex_shader.bind_attrib_pointer(gl, self.render_data.vbo);
|
||||||
gl.gl.UniformMatrix4fv(proj_mtx, 1, gl::FALSE, matrix.as_ptr() as _);
|
gl.gl.UniformMatrix4fv(self.render_data.tex_shader.proj_mtx, 1, gl::FALSE, matrix.as_ptr() as _);
|
||||||
|
|
||||||
let color = (255, 255, 255, 255);
|
let color = (255, 255, 255, 255);
|
||||||
let vertices = vec![
|
let vertices = vec![
|
||||||
|
@ -673,7 +739,12 @@ impl BackendRenderer for OpenGLRenderer {
|
||||||
VertexData { position: (1.0, 1.0), uv: (1.0, 0.0), color },
|
VertexData { position: (1.0, 1.0), uv: (1.0, 0.0), color },
|
||||||
];
|
];
|
||||||
|
|
||||||
self.draw_arrays_tex_id(gl::TRIANGLES, vertices, surf_texture, BackendShader::Texture)?;
|
self.draw_arrays_tex_id(
|
||||||
|
gl::TRIANGLES,
|
||||||
|
vertices,
|
||||||
|
self.render_data.surf_texture,
|
||||||
|
BackendShader::Texture,
|
||||||
|
)?;
|
||||||
|
|
||||||
gl.gl.Finish();
|
gl.gl.Finish();
|
||||||
}
|
}
|
||||||
|
@ -690,10 +761,10 @@ impl BackendRenderer for OpenGLRenderer {
|
||||||
if let Some((_, gl)) = self.get_context() {
|
if let Some((_, gl)) = self.get_context() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let (width_u, height_u) = (width as u32, height as u32);
|
let (width_u, height_u) = (width as u32, height as u32);
|
||||||
if self.imgui_data.last_size != (width_u, height_u) {
|
if self.render_data.last_size != (width_u, height_u) {
|
||||||
self.imgui_data.last_size = (width_u, height_u);
|
self.render_data.last_size = (width_u, height_u);
|
||||||
gl.gl.BindFramebuffer(gl::FRAMEBUFFER, 0);
|
gl.gl.BindFramebuffer(gl::FRAMEBUFFER, 0);
|
||||||
gl.gl.BindTexture(gl::TEXTURE_2D, self.imgui_data.surf_texture);
|
gl.gl.BindTexture(gl::TEXTURE_2D, self.render_data.surf_texture);
|
||||||
|
|
||||||
gl.gl.TexImage2D(
|
gl.gl.TexImage2D(
|
||||||
gl::TEXTURE_2D,
|
gl::TEXTURE_2D,
|
||||||
|
@ -710,7 +781,7 @@ impl BackendRenderer for OpenGLRenderer {
|
||||||
gl.gl.BindTexture(gl::TEXTURE_2D, 0 as _);
|
gl.gl.BindTexture(gl::TEXTURE_2D, 0 as _);
|
||||||
}
|
}
|
||||||
|
|
||||||
gl.gl.BindFramebuffer(gl::FRAMEBUFFER, self.imgui_data.surf_framebuffer);
|
gl.gl.BindFramebuffer(gl::FRAMEBUFFER, self.render_data.surf_framebuffer);
|
||||||
gl.gl.ClearColor(0.0, 0.0, 0.0, 0.0);
|
gl.gl.ClearColor(0.0, 0.0, 0.0, 0.0);
|
||||||
gl.gl.Clear(gl::COLOR_BUFFER_BIT);
|
gl.gl.Clear(gl::COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
@ -730,11 +801,29 @@ impl BackendRenderer for OpenGLRenderer {
|
||||||
|
|
||||||
gl.gl.BindBuffer(gl::ARRAY_BUFFER, 0);
|
gl.gl.BindBuffer(gl::ARRAY_BUFFER, 0);
|
||||||
gl.gl.BindBuffer(gl::ELEMENT_ARRAY_BUFFER, 0);
|
gl.gl.BindBuffer(gl::ELEMENT_ARRAY_BUFFER, 0);
|
||||||
gl.gl.UseProgram(self.imgui_data.program_fill);
|
gl.gl.UseProgram(self.render_data.fill_shader.program_id);
|
||||||
gl.gl.UniformMatrix4fv(self.imgui_data.fill_locs.proj_mtx, 1, gl::FALSE, self.def_matrix.as_ptr() as _);
|
gl.gl.UniformMatrix4fv(
|
||||||
gl.gl.UseProgram(self.imgui_data.program_tex);
|
self.render_data.fill_shader.proj_mtx,
|
||||||
gl.gl.Uniform1i(self.imgui_data.tex_locs.texture, 0);
|
1,
|
||||||
gl.gl.UniformMatrix4fv(self.imgui_data.tex_locs.proj_mtx, 1, gl::FALSE, self.def_matrix.as_ptr() as _);
|
gl::FALSE,
|
||||||
|
self.curr_matrix.as_ptr() as _,
|
||||||
|
);
|
||||||
|
gl.gl.UseProgram(self.render_data.fill_water_shader.program_id);
|
||||||
|
gl.gl.Uniform1i(self.render_data.fill_water_shader.texture, 0);
|
||||||
|
gl.gl.UniformMatrix4fv(
|
||||||
|
self.render_data.fill_water_shader.proj_mtx,
|
||||||
|
1,
|
||||||
|
gl::FALSE,
|
||||||
|
self.curr_matrix.as_ptr() as _,
|
||||||
|
);
|
||||||
|
gl.gl.UseProgram(self.render_data.tex_shader.program_id);
|
||||||
|
gl.gl.Uniform1i(self.render_data.tex_shader.texture, 0);
|
||||||
|
gl.gl.UniformMatrix4fv(
|
||||||
|
self.render_data.tex_shader.proj_mtx,
|
||||||
|
1,
|
||||||
|
gl::FALSE,
|
||||||
|
self.curr_matrix.as_ptr() as _,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -787,9 +876,8 @@ impl BackendRenderer for OpenGLRenderer {
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
vertices: Vec::new(),
|
vertices: Vec::new(),
|
||||||
locs: self.imgui_data.tex_locs,
|
shader: self.render_data.tex_shader,
|
||||||
program: self.imgui_data.program_tex,
|
vbo: self.render_data.vbo,
|
||||||
vbo: self.imgui_data.vbo,
|
|
||||||
context_active: self.context_active.clone(),
|
context_active: self.context_active.clone(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -827,9 +915,8 @@ impl BackendRenderer for OpenGLRenderer {
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
vertices: Vec::new(),
|
vertices: Vec::new(),
|
||||||
locs: self.imgui_data.tex_locs,
|
shader: self.render_data.tex_shader,
|
||||||
program: self.imgui_data.program_tex,
|
vbo: self.render_data.vbo,
|
||||||
vbo: self.imgui_data.vbo,
|
|
||||||
context_active: self.context_active.clone(),
|
context_active: self.context_active.clone(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -842,17 +929,23 @@ impl BackendRenderer for OpenGLRenderer {
|
||||||
if let Some((_, gl)) = self.get_context() {
|
if let Some((_, gl)) = self.get_context() {
|
||||||
match blend {
|
match blend {
|
||||||
BlendMode::Add => unsafe {
|
BlendMode::Add => unsafe {
|
||||||
|
gl.gl.Enable(gl::BLEND);
|
||||||
gl.gl.BlendEquation(gl::FUNC_ADD);
|
gl.gl.BlendEquation(gl::FUNC_ADD);
|
||||||
gl.gl.BlendFunc(gl::ONE, gl::ONE);
|
gl.gl.BlendFunc(gl::ONE, gl::ONE);
|
||||||
},
|
},
|
||||||
BlendMode::Alpha => unsafe {
|
BlendMode::Alpha => unsafe {
|
||||||
|
gl.gl.Enable(gl::BLEND);
|
||||||
gl.gl.BlendEquation(gl::FUNC_ADD);
|
gl.gl.BlendEquation(gl::FUNC_ADD);
|
||||||
gl.gl.BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
|
gl.gl.BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
|
||||||
},
|
},
|
||||||
BlendMode::Multiply => unsafe {
|
BlendMode::Multiply => unsafe {
|
||||||
|
gl.gl.Enable(gl::BLEND);
|
||||||
gl.gl.BlendEquation(gl::FUNC_ADD);
|
gl.gl.BlendEquation(gl::FUNC_ADD);
|
||||||
gl.gl.BlendFuncSeparate(gl::ZERO, gl::SRC_COLOR, gl::ZERO, gl::SRC_ALPHA);
|
gl.gl.BlendFuncSeparate(gl::ZERO, gl::SRC_COLOR, gl::ZERO, gl::SRC_ALPHA);
|
||||||
},
|
},
|
||||||
|
BlendMode::None => unsafe {
|
||||||
|
gl.gl.Disable(gl::BLEND);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -877,17 +970,24 @@ impl BackendRenderer for OpenGLRenderer {
|
||||||
[-1.0, -1.0, 0.0, 1.0],
|
[-1.0, -1.0, 0.0, 1.0],
|
||||||
];
|
];
|
||||||
|
|
||||||
gl.gl.UseProgram(self.imgui_data.program_fill);
|
gl.gl.UseProgram(self.render_data.fill_shader.program_id);
|
||||||
gl.gl.UniformMatrix4fv(
|
gl.gl.UniformMatrix4fv(
|
||||||
self.imgui_data.fill_locs.proj_mtx,
|
self.render_data.fill_shader.proj_mtx,
|
||||||
1,
|
1,
|
||||||
gl::FALSE,
|
gl::FALSE,
|
||||||
self.curr_matrix.as_ptr() as _,
|
self.curr_matrix.as_ptr() as _,
|
||||||
);
|
);
|
||||||
gl.gl.UseProgram(self.imgui_data.program_tex);
|
gl.gl.UseProgram(self.render_data.fill_water_shader.program_id);
|
||||||
gl.gl.Uniform1i(self.imgui_data.tex_locs.texture, 0);
|
|
||||||
gl.gl.UniformMatrix4fv(
|
gl.gl.UniformMatrix4fv(
|
||||||
self.imgui_data.tex_locs.proj_mtx,
|
self.render_data.fill_water_shader.proj_mtx,
|
||||||
|
1,
|
||||||
|
gl::FALSE,
|
||||||
|
self.curr_matrix.as_ptr() as _,
|
||||||
|
);
|
||||||
|
gl.gl.UseProgram(self.render_data.tex_shader.program_id);
|
||||||
|
gl.gl.Uniform1i(self.render_data.tex_shader.texture, 0);
|
||||||
|
gl.gl.UniformMatrix4fv(
|
||||||
|
self.render_data.tex_shader.proj_mtx,
|
||||||
1,
|
1,
|
||||||
gl::FALSE,
|
gl::FALSE,
|
||||||
self.curr_matrix.as_ptr() as _,
|
self.curr_matrix.as_ptr() as _,
|
||||||
|
@ -898,23 +998,30 @@ impl BackendRenderer for OpenGLRenderer {
|
||||||
} else {
|
} else {
|
||||||
self.curr_matrix = self.def_matrix;
|
self.curr_matrix = self.def_matrix;
|
||||||
|
|
||||||
gl.gl.UseProgram(self.imgui_data.program_fill);
|
gl.gl.UseProgram(self.render_data.fill_shader.program_id);
|
||||||
gl.gl.UniformMatrix4fv(
|
gl.gl.UniformMatrix4fv(
|
||||||
self.imgui_data.fill_locs.proj_mtx,
|
self.render_data.fill_shader.proj_mtx,
|
||||||
1,
|
1,
|
||||||
gl::FALSE,
|
gl::FALSE,
|
||||||
self.def_matrix.as_ptr() as _,
|
self.curr_matrix.as_ptr() as _,
|
||||||
);
|
);
|
||||||
gl.gl.UseProgram(self.imgui_data.program_tex);
|
gl.gl.UseProgram(self.render_data.fill_water_shader.program_id);
|
||||||
gl.gl.Uniform1i(self.imgui_data.tex_locs.texture, 0);
|
|
||||||
gl.gl.UniformMatrix4fv(
|
gl.gl.UniformMatrix4fv(
|
||||||
self.imgui_data.tex_locs.proj_mtx,
|
self.render_data.fill_water_shader.proj_mtx,
|
||||||
1,
|
1,
|
||||||
gl::FALSE,
|
gl::FALSE,
|
||||||
self.def_matrix.as_ptr() as _,
|
self.curr_matrix.as_ptr() as _,
|
||||||
);
|
);
|
||||||
gl.gl.BindFramebuffer(gl::FRAMEBUFFER, self.imgui_data.surf_framebuffer);
|
gl.gl.UseProgram(self.render_data.tex_shader.program_id);
|
||||||
gl.gl.Viewport(0, 0, self.imgui_data.last_size.0 as _, self.imgui_data.last_size.1 as _);
|
gl.gl.Uniform1i(self.render_data.tex_shader.texture, 0);
|
||||||
|
gl.gl.UniformMatrix4fv(
|
||||||
|
self.render_data.tex_shader.proj_mtx,
|
||||||
|
1,
|
||||||
|
gl::FALSE,
|
||||||
|
self.curr_matrix.as_ptr() as _,
|
||||||
|
);
|
||||||
|
gl.gl.BindFramebuffer(gl::FRAMEBUFFER, self.render_data.surf_framebuffer);
|
||||||
|
gl.gl.Viewport(0, 0, self.render_data.last_size.0 as _, self.render_data.last_size.1 as _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -928,7 +1035,7 @@ impl BackendRenderer for OpenGLRenderer {
|
||||||
unsafe {
|
unsafe {
|
||||||
if let Some(gl) = &GL_PROC {
|
if let Some(gl) = &GL_PROC {
|
||||||
let color = color.to_rgba();
|
let color = color.to_rgba();
|
||||||
let mut uv = self.imgui_data.font_tex_size;
|
let mut uv = self.render_data.font_tex_size;
|
||||||
uv.0 = 0.0 / uv.0;
|
uv.0 = 0.0 / uv.0;
|
||||||
uv.1 = 0.0 / uv.1;
|
uv.1 = 0.0 / uv.1;
|
||||||
|
|
||||||
|
@ -941,45 +1048,10 @@ impl BackendRenderer for OpenGLRenderer {
|
||||||
VertexData { position: (rect.right as _, rect.bottom as _), uv, color },
|
VertexData { position: (rect.right as _, rect.bottom as _), uv, color },
|
||||||
];
|
];
|
||||||
|
|
||||||
if gl.gl.BindSampler.is_loaded() {
|
self.render_data.fill_shader.bind_attrib_pointer(gl, self.render_data.vbo);
|
||||||
gl.gl.BindSampler(0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
gl.gl.UseProgram(self.imgui_data.program_fill);
|
gl.gl.BindTexture(gl::TEXTURE_2D, self.render_data.font_texture);
|
||||||
gl.gl.BindBuffer(gl::ARRAY_BUFFER, self.imgui_data.vbo);
|
gl.gl.BindBuffer(gl::ARRAY_BUFFER, self.render_data.vbo);
|
||||||
gl.gl.EnableVertexAttribArray(self.imgui_data.fill_locs.position);
|
|
||||||
gl.gl.EnableVertexAttribArray(self.imgui_data.fill_locs.uv);
|
|
||||||
gl.gl.EnableVertexAttribArray(self.imgui_data.fill_locs.color);
|
|
||||||
|
|
||||||
gl.gl.VertexAttribPointer(
|
|
||||||
self.imgui_data.fill_locs.position,
|
|
||||||
2,
|
|
||||||
gl::FLOAT,
|
|
||||||
gl::FALSE,
|
|
||||||
mem::size_of::<VertexData>() as _,
|
|
||||||
field_offset::<VertexData, _, _>(|v| &v.position) as _,
|
|
||||||
);
|
|
||||||
|
|
||||||
gl.gl.VertexAttribPointer(
|
|
||||||
self.imgui_data.fill_locs.uv,
|
|
||||||
2,
|
|
||||||
gl::FLOAT,
|
|
||||||
gl::FALSE,
|
|
||||||
mem::size_of::<VertexData>() as _,
|
|
||||||
field_offset::<VertexData, _, _>(|v| &v.uv) as _,
|
|
||||||
);
|
|
||||||
|
|
||||||
gl.gl.VertexAttribPointer(
|
|
||||||
self.imgui_data.fill_locs.color,
|
|
||||||
4,
|
|
||||||
gl::UNSIGNED_BYTE,
|
|
||||||
gl::TRUE,
|
|
||||||
mem::size_of::<VertexData>() as _,
|
|
||||||
field_offset::<VertexData, _, _>(|v| &v.color) as _,
|
|
||||||
);
|
|
||||||
|
|
||||||
gl.gl.BindTexture(gl::TEXTURE_2D, self.imgui_data.font_texture);
|
|
||||||
gl.gl.BindBuffer(gl::ARRAY_BUFFER, self.imgui_data.vbo);
|
|
||||||
gl.gl.BufferData(
|
gl.gl.BufferData(
|
||||||
gl::ARRAY_BUFFER,
|
gl::ARRAY_BUFFER,
|
||||||
(vertices.len() * mem::size_of::<VertexData>()) as _,
|
(vertices.len() * mem::size_of::<VertexData>()) as _,
|
||||||
|
@ -1010,7 +1082,7 @@ impl BackendRenderer for OpenGLRenderer {
|
||||||
gl.gl.Enable(gl::SCISSOR_TEST);
|
gl.gl.Enable(gl::SCISSOR_TEST);
|
||||||
gl.gl.Scissor(
|
gl.gl.Scissor(
|
||||||
rect.left as GLint,
|
rect.left as GLint,
|
||||||
self.imgui_data.last_size.1 as GLint - rect.bottom as GLint,
|
self.render_data.last_size.1 as GLint - rect.bottom as GLint,
|
||||||
rect.width() as GLint,
|
rect.width() as GLint,
|
||||||
rect.height() as GLint,
|
rect.height() as GLint,
|
||||||
);
|
);
|
||||||
|
@ -1069,23 +1141,21 @@ impl BackendRenderer for OpenGLRenderer {
|
||||||
[-1.0, 1.0, 0.0, 1.0],
|
[-1.0, 1.0, 0.0, 1.0],
|
||||||
];
|
];
|
||||||
|
|
||||||
gl.gl.UseProgram(self.imgui_data.program_tex);
|
gl.gl.UseProgram(self.render_data.tex_shader.program_id);
|
||||||
gl.gl.Uniform1i(self.imgui_data.tex_locs.texture, 0);
|
gl.gl.Uniform1i(self.render_data.tex_shader.texture, 0);
|
||||||
gl.gl.UniformMatrix4fv(self.imgui_data.tex_locs.proj_mtx, 1, gl::FALSE, matrix.as_ptr() as _);
|
gl.gl.UniformMatrix4fv(self.render_data.tex_shader.proj_mtx, 1, gl::FALSE, matrix.as_ptr() as _);
|
||||||
|
|
||||||
if gl.gl.BindSampler.is_loaded() {
|
if gl.gl.BindSampler.is_loaded() {
|
||||||
gl.gl.BindSampler(0, 0);
|
gl.gl.BindSampler(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// let vao = return_param(|x| gl.gl.GenVertexArrays(1, x));
|
gl.gl.BindBuffer(gl::ARRAY_BUFFER, self.render_data.vbo);
|
||||||
//gl.gl.BindVertexArray(vao);
|
gl.gl.EnableVertexAttribArray(self.render_data.tex_shader.position);
|
||||||
gl.gl.BindBuffer(gl::ARRAY_BUFFER, self.imgui_data.vbo);
|
gl.gl.EnableVertexAttribArray(self.render_data.tex_shader.uv);
|
||||||
gl.gl.EnableVertexAttribArray(self.imgui_data.tex_locs.position);
|
gl.gl.EnableVertexAttribArray(self.render_data.tex_shader.color);
|
||||||
gl.gl.EnableVertexAttribArray(self.imgui_data.tex_locs.uv);
|
|
||||||
gl.gl.EnableVertexAttribArray(self.imgui_data.tex_locs.color);
|
|
||||||
|
|
||||||
gl.gl.VertexAttribPointer(
|
gl.gl.VertexAttribPointer(
|
||||||
self.imgui_data.tex_locs.position,
|
self.render_data.tex_shader.position,
|
||||||
2,
|
2,
|
||||||
gl::FLOAT,
|
gl::FLOAT,
|
||||||
gl::FALSE,
|
gl::FALSE,
|
||||||
|
@ -1094,7 +1164,7 @@ impl BackendRenderer for OpenGLRenderer {
|
||||||
);
|
);
|
||||||
|
|
||||||
gl.gl.VertexAttribPointer(
|
gl.gl.VertexAttribPointer(
|
||||||
self.imgui_data.tex_locs.uv,
|
self.render_data.tex_shader.uv,
|
||||||
2,
|
2,
|
||||||
gl::FLOAT,
|
gl::FLOAT,
|
||||||
gl::FALSE,
|
gl::FALSE,
|
||||||
|
@ -1103,7 +1173,7 @@ impl BackendRenderer for OpenGLRenderer {
|
||||||
);
|
);
|
||||||
|
|
||||||
gl.gl.VertexAttribPointer(
|
gl.gl.VertexAttribPointer(
|
||||||
self.imgui_data.tex_locs.color,
|
self.render_data.tex_shader.color,
|
||||||
4,
|
4,
|
||||||
gl::UNSIGNED_BYTE,
|
gl::UNSIGNED_BYTE,
|
||||||
gl::TRUE,
|
gl::TRUE,
|
||||||
|
@ -1115,7 +1185,7 @@ impl BackendRenderer for OpenGLRenderer {
|
||||||
let vtx_buffer = draw_list.vtx_buffer();
|
let vtx_buffer = draw_list.vtx_buffer();
|
||||||
let idx_buffer = draw_list.idx_buffer();
|
let idx_buffer = draw_list.idx_buffer();
|
||||||
|
|
||||||
gl.gl.BindBuffer(gl::ARRAY_BUFFER, self.imgui_data.vbo);
|
gl.gl.BindBuffer(gl::ARRAY_BUFFER, self.render_data.vbo);
|
||||||
gl.gl.BufferData(
|
gl.gl.BufferData(
|
||||||
gl::ARRAY_BUFFER,
|
gl::ARRAY_BUFFER,
|
||||||
(vtx_buffer.len() * mem::size_of::<DrawVert>()) as _,
|
(vtx_buffer.len() * mem::size_of::<DrawVert>()) as _,
|
||||||
|
@ -1123,7 +1193,7 @@ impl BackendRenderer for OpenGLRenderer {
|
||||||
gl::STREAM_DRAW,
|
gl::STREAM_DRAW,
|
||||||
);
|
);
|
||||||
|
|
||||||
gl.gl.BindBuffer(gl::ELEMENT_ARRAY_BUFFER, self.imgui_data.ebo);
|
gl.gl.BindBuffer(gl::ELEMENT_ARRAY_BUFFER, self.render_data.ebo);
|
||||||
gl.gl.BufferData(
|
gl.gl.BufferData(
|
||||||
gl::ELEMENT_ARRAY_BUFFER,
|
gl::ELEMENT_ARRAY_BUFFER,
|
||||||
(idx_buffer.len() * mem::size_of::<DrawIdx>()) as _,
|
(idx_buffer.len() * mem::size_of::<DrawIdx>()) as _,
|
||||||
|
@ -1163,7 +1233,6 @@ impl BackendRenderer for OpenGLRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
gl.gl.Disable(gl::SCISSOR_TEST);
|
gl.gl.Disable(gl::SCISSOR_TEST);
|
||||||
//gl.gl.DeleteVertexArrays(1, &vao);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1214,78 +1283,23 @@ impl OpenGLRenderer {
|
||||||
&mut self,
|
&mut self,
|
||||||
vert_type: GLenum,
|
vert_type: GLenum,
|
||||||
vertices: Vec<VertexData>,
|
vertices: Vec<VertexData>,
|
||||||
texture: u32,
|
mut texture: u32,
|
||||||
shader: BackendShader,
|
shader: BackendShader,
|
||||||
) -> GameResult<()> {
|
) -> GameResult<()> {
|
||||||
if let Some(gl) = &GL_PROC {
|
if let Some(gl) = &GL_PROC {
|
||||||
match shader {
|
match shader {
|
||||||
BackendShader::Fill => {
|
BackendShader::Fill => {
|
||||||
gl.gl.UseProgram(self.imgui_data.program_fill);
|
self.render_data.fill_shader.bind_attrib_pointer(gl, self.render_data.vbo)?;
|
||||||
gl.gl.BindBuffer(gl::ARRAY_BUFFER, self.imgui_data.vbo);
|
|
||||||
gl.gl.EnableVertexAttribArray(self.imgui_data.fill_locs.position);
|
|
||||||
gl.gl.EnableVertexAttribArray(self.imgui_data.fill_locs.uv);
|
|
||||||
gl.gl.EnableVertexAttribArray(self.imgui_data.fill_locs.color);
|
|
||||||
|
|
||||||
gl.gl.VertexAttribPointer(
|
|
||||||
self.imgui_data.fill_locs.position,
|
|
||||||
2,
|
|
||||||
gl::FLOAT,
|
|
||||||
gl::FALSE,
|
|
||||||
mem::size_of::<VertexData>() as _,
|
|
||||||
field_offset::<VertexData, _, _>(|v| &v.position) as _,
|
|
||||||
);
|
|
||||||
|
|
||||||
gl.gl.VertexAttribPointer(
|
|
||||||
self.imgui_data.fill_locs.uv,
|
|
||||||
2,
|
|
||||||
gl::FLOAT,
|
|
||||||
gl::FALSE,
|
|
||||||
mem::size_of::<VertexData>() as _,
|
|
||||||
field_offset::<VertexData, _, _>(|v| &v.uv) as _,
|
|
||||||
);
|
|
||||||
|
|
||||||
gl.gl.VertexAttribPointer(
|
|
||||||
self.imgui_data.fill_locs.color,
|
|
||||||
4,
|
|
||||||
gl::UNSIGNED_BYTE,
|
|
||||||
gl::TRUE,
|
|
||||||
mem::size_of::<VertexData>() as _,
|
|
||||||
field_offset::<VertexData, _, _>(|v| &v.color) as _,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
BackendShader::Texture => {
|
BackendShader::Texture => {
|
||||||
gl.gl.UseProgram(self.imgui_data.program_tex);
|
self.render_data.tex_shader.bind_attrib_pointer(gl, self.render_data.vbo)?;
|
||||||
gl.gl.BindBuffer(gl::ARRAY_BUFFER, self.imgui_data.vbo);
|
}
|
||||||
gl.gl.EnableVertexAttribArray(self.imgui_data.tex_locs.position);
|
BackendShader::WaterFill(scale, t, frame_pos) => {
|
||||||
gl.gl.EnableVertexAttribArray(self.imgui_data.tex_locs.uv);
|
self.render_data.fill_water_shader.bind_attrib_pointer(gl, self.render_data.vbo)?;
|
||||||
gl.gl.EnableVertexAttribArray(self.imgui_data.tex_locs.color);
|
gl.gl.Uniform1f(self.render_data.fill_water_shader.scale, scale);
|
||||||
|
gl.gl.Uniform1f(self.render_data.fill_water_shader.time, t);
|
||||||
gl.gl.VertexAttribPointer(
|
gl.gl.Uniform2f(self.render_data.fill_water_shader.frame_offset, frame_pos.0, frame_pos.1);
|
||||||
self.imgui_data.tex_locs.position,
|
texture = self.render_data.surf_texture;
|
||||||
2,
|
|
||||||
gl::FLOAT,
|
|
||||||
gl::FALSE,
|
|
||||||
mem::size_of::<VertexData>() as _,
|
|
||||||
field_offset::<VertexData, _, _>(|v| &v.position) as _,
|
|
||||||
);
|
|
||||||
|
|
||||||
gl.gl.VertexAttribPointer(
|
|
||||||
self.imgui_data.tex_locs.uv,
|
|
||||||
2,
|
|
||||||
gl::FLOAT,
|
|
||||||
gl::FALSE,
|
|
||||||
mem::size_of::<VertexData>() as _,
|
|
||||||
field_offset::<VertexData, _, _>(|v| &v.uv) as _,
|
|
||||||
);
|
|
||||||
|
|
||||||
gl.gl.VertexAttribPointer(
|
|
||||||
self.imgui_data.tex_locs.color,
|
|
||||||
4,
|
|
||||||
gl::UNSIGNED_BYTE,
|
|
||||||
gl::TRUE,
|
|
||||||
mem::size_of::<VertexData>() as _,
|
|
||||||
field_offset::<VertexData, _, _>(|v| &v.color) as _,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
35
src/map.rs
35
src/map.rs
|
@ -302,7 +302,7 @@ impl Map {
|
||||||
self.attrib[*self.tiles.get(self.width as usize * y + x).unwrap_or(&0u8) as usize]
|
self.attrib[*self.tiles.get(self.width as usize * y + x).unwrap_or(&0u8) as usize]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_water_regions(&self) -> Vec<(WaterRegionType, Rect<u16>)> {
|
pub fn find_water_regions(&self, water_params: &WaterParams) -> Vec<(WaterRegionType, Rect<u16>, u8)> {
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
|
|
||||||
if self.height == 0 || self.width == 0 {
|
if self.height == 0 || self.width == 0 {
|
||||||
|
@ -310,7 +310,7 @@ impl Map {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut walked = vec![false; self.width as usize * self.height as usize];
|
let mut walked = vec![false; self.width as usize * self.height as usize];
|
||||||
let mut rects = Vec::<Rect<u16>>::new();
|
let mut rects = Vec::<(Rect<u16>, u8)>::new();
|
||||||
|
|
||||||
for x in 0..self.width {
|
for x in 0..self.width {
|
||||||
for y in 0..self.height {
|
for y in 0..self.height {
|
||||||
|
@ -325,6 +325,9 @@ impl Map {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let color_tile_idx = self.tiles[idx];
|
||||||
|
let region_color = water_params.get_entry(color_tile_idx).color_middle;
|
||||||
|
|
||||||
walked[idx] = true;
|
walked[idx] = true;
|
||||||
let mut rect = Rect::new(x, y, x, y);
|
let mut rect = Rect::new(x, y, x, y);
|
||||||
let mut queue = vec![(0b1100, x, y)];
|
let mut queue = vec![(0b1100, x, y)];
|
||||||
|
@ -371,7 +374,12 @@ impl Map {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if walked[self.width as usize * ey as usize + ex as usize] {
|
let idx = self.width as usize * ey as usize + ex as usize;
|
||||||
|
if walked[idx] {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if water_params.get_entry(self.tiles[idx]).color_middle != region_color {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,20 +403,20 @@ impl Map {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rects.push(rect);
|
rects.push((rect, color_tile_idx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
walked.fill(false);
|
walked.fill(false);
|
||||||
|
|
||||||
for mut rect in rects {
|
for (mut rect, color_idx) in rects {
|
||||||
let line = rect.top;
|
let line = rect.top;
|
||||||
let line_up = rect.top - 1;
|
let line_up = rect.top - 1;
|
||||||
let min_x = rect.left;
|
let min_x = rect.left;
|
||||||
let max_x = rect.right;
|
let max_x = rect.right;
|
||||||
|
|
||||||
rect.top += 1;
|
rect.top += 1;
|
||||||
result.push((WaterRegionType::WaterDepth, rect));
|
result.push((WaterRegionType::WaterDepth, rect, color_idx));
|
||||||
|
|
||||||
let mut x = min_x;
|
let mut x = min_x;
|
||||||
let mut length = 0;
|
let mut length = 0;
|
||||||
|
@ -430,6 +438,7 @@ impl Map {
|
||||||
result.push((
|
result.push((
|
||||||
if make_water_line { WaterRegionType::WaterLine } else { WaterRegionType::WaterDepth },
|
if make_water_line { WaterRegionType::WaterLine } else { WaterRegionType::WaterDepth },
|
||||||
bounds,
|
bounds,
|
||||||
|
color_idx,
|
||||||
));
|
));
|
||||||
length = 0;
|
length = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -445,6 +454,7 @@ impl Map {
|
||||||
result.push((
|
result.push((
|
||||||
if make_water_line { WaterRegionType::WaterLine } else { WaterRegionType::WaterDepth },
|
if make_water_line { WaterRegionType::WaterLine } else { WaterRegionType::WaterDepth },
|
||||||
bounds,
|
bounds,
|
||||||
|
color_idx,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,6 +522,16 @@ pub struct WaterParamEntry {
|
||||||
pub color_bottom: Color,
|
pub color_bottom: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for WaterParamEntry {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
color_top: Color::from_rgba(102, 153, 204, 150),
|
||||||
|
color_middle: Color::from_rgba(102, 153, 204, 75),
|
||||||
|
color_bottom: Color::from_rgba(102, 153, 204, 75),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct WaterParams {
|
pub struct WaterParams {
|
||||||
entries: HashMap<u8, WaterParamEntry>,
|
entries: HashMap<u8, WaterParamEntry>,
|
||||||
}
|
}
|
||||||
|
@ -572,7 +592,8 @@ impl WaterParams {
|
||||||
let entry = WaterParamEntry { color_top, color_middle, color_bottom };
|
let entry = WaterParamEntry { color_top, color_middle, color_bottom };
|
||||||
|
|
||||||
for i in tile_min..=tile_max {
|
for i in tile_min..=tile_max {
|
||||||
self.entries.insert(i, entry);
|
let e = self.entries.entry(i);
|
||||||
|
e.or_insert(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => return Err(GameError::IOError(Arc::new(e))),
|
Err(e) => return Err(GameError::IOError(Arc::new(e))),
|
||||||
|
|
|
@ -121,7 +121,8 @@ impl GameScene {
|
||||||
water_params.load_from(water_param_file)?;
|
water_params.load_from(water_param_file)?;
|
||||||
info!("Loaded water parameters file.");
|
info!("Loaded water parameters file.");
|
||||||
|
|
||||||
water_renderer.initialize(stage.map.find_water_regions());
|
let regions = stage.map.find_water_regions(&water_params);
|
||||||
|
water_renderer.initialize(regions, &water_params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue