16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-18 04:19:19 +02:00

work, proper gui gamma, restore cab picking

This commit is contained in:
milek7
2018-07-12 23:28:39 +02:00
parent d48fd9cf54
commit c94820e8b7
9 changed files with 186 additions and 83 deletions

View File

@@ -322,6 +322,7 @@ int main(int argc, char *argv[])
glfwWindowHint(GLFW_GREEN_BITS, vmode->greenBits);
glfwWindowHint(GLFW_BLUE_BITS, vmode->blueBits);
glfwWindowHint(GLFW_REFRESH_RATE, vmode->refreshRate);
glfwWindowHint(GLFW_SRGB_CAPABLE, GLFW_TRUE);
glfwWindowHint(GLFW_AUTO_ICONIFY, GLFW_FALSE);
if( Global.iMultisampling > 0 ) {
@@ -448,17 +449,17 @@ int main(int argc, char *argv[])
glfwPollEvents();
if (take_screenshot)
{
make_screenshot();
take_screenshot = false;
}
if (!World.Update())
break;
if (!GfxRenderer.Render())
break;
if (take_screenshot)
{
make_screenshot();
take_screenshot = false;
}
if (input::motiontelemetry)
input::motiontelemetry->update();
input::Keyboard.poll();

View File

@@ -609,9 +609,6 @@ opengl_texture::create() {
}
}
::glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, ( wraps == true ? GL_REPEAT : GL_CLAMP_TO_EDGE ) );
::glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, ( wrapt == true ? GL_REPEAT : GL_CLAMP_TO_EDGE ) );
// upload texture data
int dataoffset = 0,
datasize = 0,
@@ -619,12 +616,22 @@ opengl_texture::create() {
dataheight = data_height;
if (is_rendertarget)
{
::glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
::glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
if (data_components == GL_DEPTH_COMPONENT)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
}
glTexImage2D(GL_TEXTURE_2D, 0, data_format, data_width, data_height, 0, data_components, data_type, nullptr);
}
else
{
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (wraps == true ? GL_REPEAT : GL_CLAMP_TO_EDGE));
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (wrapt == true ? GL_REPEAT : GL_CLAMP_TO_EDGE));
set_filtering();
for( int maplevel = 0; maplevel < data_mapcount; ++maplevel ) {

View File

@@ -98,6 +98,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE);
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
GLboolean last_enable_srgb = glIsEnabled(GL_FRAMEBUFFER_SRGB);
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
glEnable(GL_BLEND);
@@ -107,6 +108,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
glDisable(GL_DEPTH_TEST);
glEnable(GL_SCISSOR_TEST);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_FRAMEBUFFER_SRGB);
// Setup viewport, orthographic projection matrix
// Our visible imgui space lies from draw_data->DisplayPps (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is typically (0,0) for single viewport apps.
@@ -192,6 +194,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE);
if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);
if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST);
if (last_enable_srgb) glEnable(GL_FRAMEBUFFER_SRGB); else glDisable(GL_FRAMEBUFFER_SRGB);
glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]);
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
@@ -254,7 +257,7 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
"void main()\n"
"{\n"
" Frag_UV = UV;\n"
" Frag_Color = Color;\n"
" Frag_Color = vec4(pow(Color.rgb, vec3(2.2)), Color.a);\n"
" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
"}\n";

View File

@@ -175,6 +175,14 @@ opengl_renderer::Init( GLFWwindow *Window ) {
m_shadow_shader = std::unique_ptr<gl::program>(prog);
}
{
gl::shader vert("pick.vert");
gl::shader frag("pick.frag");
gl::program *prog = new gl::program_mvp({ vert, frag });
prog->init();
m_pick_shader = std::unique_ptr<gl::program>(prog);
}
m_invalid_material = Fetch_Material("invalid");
m_main_fb = std::make_unique<gl::framebuffer>();
@@ -199,6 +207,14 @@ opengl_renderer::Init( GLFWwindow *Window ) {
if (!m_shadow_fb->is_complete())
return false;
m_pick_tex = std::make_unique<opengl_texture>();
m_pick_tex->alloc_rendertarget(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, EU07_PICKBUFFERSIZE, EU07_PICKBUFFERSIZE);
m_pick_rb = std::make_unique<gl::renderbuffer>();
m_pick_rb->alloc(GL_DEPTH_COMPONENT24, EU07_PICKBUFFERSIZE, EU07_PICKBUFFERSIZE);
m_pick_fb = std::make_unique<gl::framebuffer>();
m_pick_fb->attach(*m_pick_tex, GL_COLOR_ATTACHMENT0);
m_pick_fb->attach(*m_pick_rb, GL_DEPTH_ATTACHMENT);
return true;
}
@@ -284,10 +300,8 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
glDebug("rendermode::color");
{
glActiveTexture(GL_TEXTURE10);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
m_textures.reset_unit_cache();
setup_shadow_map(nullptr);
glDebug("render shadowmap start");
Timer::subsystem.gfx_shadows.start();
@@ -351,21 +365,13 @@ m_textures.reset_unit_cache();
scene_ubo->update(scene_ubs);
// opaque parts...
setup_drawing( false );
setup_shadow_map(*m_shadow_tex);
setup_shadow_map(m_shadow_tex.get());
if( false == FreeFlyModeFlag ) {
glDebug("render cab opaque");
//setup_shadow_map( m_cabshadowtexture, m_cabshadowtexturematrix );
// cache shadow colour in case we need to account for cab light
auto const shadowcolor { m_shadowcolor };
auto const *vehicle{ World.Train->Dynamic() };
if( vehicle->InteriorLightLevel > 0.f ) {
setup_shadow_color( glm::min( colors::white, shadowcolor + glm::vec4( vehicle->InteriorLight * vehicle->InteriorLightLevel, 1.f ) ) );
}
auto const *vehicle{ World.Train->Dynamic() };
Render_cab( vehicle, false );
if( vehicle->InteriorLightLevel > 0.f ) {
setup_shadow_color( shadowcolor );
}
}
glDebug("render opaque region");
@@ -381,15 +387,8 @@ m_textures.reset_unit_cache();
// cab render is performed without shadows, due to low resolution and number of models without windows :|
//setup_shadow_map( m_cabshadowtexture, m_cabshadowtexturematrix );
// cache shadow colour in case we need to account for cab light
auto const shadowcolor{ m_shadowcolor };
auto const *vehicle{ World.Train->Dynamic() };
if( vehicle->InteriorLightLevel > 0.f ) {
setup_shadow_color( glm::min( colors::white, shadowcolor + glm::vec4( vehicle->InteriorLight * vehicle->InteriorLightLevel, 1.f ) ) );
}
Render_cab( vehicle, true );
if( vehicle->InteriorLightLevel > 0.f ) {
setup_shadow_color( shadowcolor );
}
}
/*
@@ -403,7 +402,6 @@ m_textures.reset_unit_cache();
}
*/
glDebug("color pass done");
}
glEnable(GL_FRAMEBUFFER_SRGB);
@@ -412,7 +410,10 @@ m_textures.reset_unit_cache();
m_textures.reset_unit_cache();
glDisable(GL_FRAMEBUFFER_SRGB);
glDebug("uilayer render");
UILayer.render();
glDebug("rendermode::color end");
break;
}
@@ -428,7 +429,7 @@ m_textures.reset_unit_cache();
glViewport(0, 0, m_shadowbuffersize, m_shadowbuffersize);
m_shadow_fb->bind();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
m_shadow_fb->clear();
setup_matrices();
setup_drawing(false);
@@ -446,6 +447,8 @@ m_textures.reset_unit_cache();
m_shadow_fb->unbind();
glDebug("rendermode::end");
break;
}
@@ -458,6 +461,27 @@ m_textures.reset_unit_cache();
}
case rendermode::pickcontrols: {
if (!World.InitPerformed() || !World.Train)
break;
glDebug("rendermode::pickcontrols");
glViewport(0, 0, EU07_PICKBUFFERSIZE, EU07_PICKBUFFERSIZE);
m_pick_fb->bind();
m_pick_fb->clear();
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
m_pickcontrolsitems.clear();
setup_matrices();
setup_drawing(false);
Render_cab(World.Train->Dynamic());
m_pick_fb->unbind();
glDebug("rendermode::pickcontrols end");
break;
}
@@ -607,6 +631,21 @@ opengl_renderer::setup_pass( renderpass_config &Config, rendermode const Mode, f
break;
}
case rendermode::pickcontrols:
case rendermode::pickscenery:
{
// modelview
camera.position() = Global.pCameraPosition;
World.Camera.SetMatrix(viewmatrix);
// projection
camera.projection() *=
glm::perspective(
glm::radians(Global.FieldOfView / Global.ZoomFactor),
std::max(1.f, (float)Global.iWindowWidth) / std::max(1.f, (float)Global.iWindowHeight),
0.1f * Global.ZoomFactor,
Config.draw_range * Global.fDistanceFactor);
break;
}
default: {
break;
}
@@ -649,6 +688,8 @@ opengl_renderer::setup_drawing( bool const Alpha ) {
switch( m_renderpass.draw_mode ) {
case rendermode::color:
case rendermode::reflections: {
glCullFace(GL_BACK);
// setup fog
if( Global.fFogEnd > 0 ) {
// m7t setup fog ubo
@@ -657,6 +698,10 @@ opengl_renderer::setup_drawing( bool const Alpha ) {
break;
}
case rendermode::shadows:
{
glCullFace(GL_FRONT);
break;
}
case rendermode::cabshadows:
case rendermode::pickcontrols:
case rendermode::pickscenery:
@@ -671,17 +716,16 @@ opengl_renderer::setup_drawing( bool const Alpha ) {
// configures shadow texture unit for specified shadow map and conersion matrix
void
opengl_renderer::setup_shadow_map( opengl_texture &tex ) {
opengl_renderer::setup_shadow_map( opengl_texture *tex ) {
glActiveTexture(GL_TEXTURE10);
tex.bind();
if (tex)
tex->bind();
else
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
m_textures.reset_unit_cache();
}
void
opengl_renderer::setup_shadow_color( glm::vec4 const &Shadowcolor ) {
}
void
opengl_renderer::setup_environment_light( TEnvironmentType const Environment ) {
@@ -940,8 +984,6 @@ opengl_renderer::Render( section_sequence::iterator First, section_sequence::ite
break;
}
case rendermode::shadows: {
// for shadows it is better to cull front faces
glCullFace(GL_FRONT);
break; }
case rendermode::pickscenery: {
break;
@@ -1007,8 +1049,6 @@ opengl_renderer::Render( section_sequence::iterator First, section_sequence::ite
switch( m_renderpass.draw_mode ) {
case rendermode::shadows: {
// restore standard face cull mode
::glCullFace( GL_BACK );
break; }
default: {
break; }
@@ -1362,7 +1402,12 @@ opengl_renderer::Render_cab( TDynamicObject const *Dynamic, bool const Alpha ) {
break;
}
case rendermode::cabshadows:
break;
case rendermode::pickcontrols:
{
Render(Dynamic->mdKabina, Dynamic->Material(), 0.0);
break;
}
default: {
break;
}
@@ -1522,7 +1567,18 @@ opengl_renderer::Render( TSubModel *Submodel ) {
}
case rendermode::cabshadows:
case rendermode::pickscenery:
break;
case rendermode::pickcontrols:
{
m_pick_shader->bind();
// control picking applies individual colour for each submodel
m_pickcontrolsitems.emplace_back(Submodel);
model_ubs.param[0] = glm::vec4(pick_color(m_pickcontrolsitems.size()), 1.0f);
model_ubs.set_modelview(OpenGLMatrices.data(GL_MODELVIEW));
model_ubo->update(model_ubs);
m_geometry.draw(Submodel->m_geometry);
break;
}
default: {
break;
}
@@ -1687,6 +1743,7 @@ opengl_renderer::Render( scene::basic_cell::path_sequence::const_iterator First,
switch( m_renderpass.draw_mode ) {
case rendermode::shadows: {
// NOTE: roads-based platforms tend to miss parts of shadows if rendered with either back or front culling
glDisable(GL_CULL_FACE);
break;
}
default: {
@@ -2329,7 +2386,34 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
// utility methods
TSubModel const *
opengl_renderer::Update_Pick_Control() {
return nullptr;
Render_pass(rendermode::pickcontrols);
// determine point to examine
glm::dvec2 mousepos;
glfwGetCursorPos(m_window, &mousepos.x, &mousepos.y);
mousepos.y = Global.iWindowHeight - mousepos.y; // cursor coordinates are flipped compared to opengl
glm::ivec2 pickbufferpos;
pickbufferpos = glm::ivec2{
mousepos.x * EU07_PICKBUFFERSIZE / std::max(1, Global.iWindowWidth),
mousepos.y * EU07_PICKBUFFERSIZE / std::max(1, Global.iWindowHeight) };
unsigned char pickreadout[3];
//m7t: ! replace with PBO and wait frame or two to improve performance
m_pick_fb->bind();
::glReadPixels(pickbufferpos.x, pickbufferpos.y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, pickreadout);
m_pick_fb->unbind();
auto const controlindex = pick_index(glm::ivec3{ pickreadout[0], pickreadout[1], pickreadout[2] });
TSubModel const *control{ nullptr };
if ((controlindex > 0)
&& (controlindex <= m_pickcontrolsitems.size())) {
control = m_pickcontrolsitems[controlindex - 1];
}
m_pickcontrolitem = control;
return control;
}
scene::basic_node const *
@@ -2575,20 +2659,6 @@ opengl_renderer::Init_caps() {
glm::vec3
opengl_renderer::pick_color( std::size_t const Index ) {
/*
// pick colours are set with step of 4 for some slightly easier visual debugging. not strictly needed but, eh
int const colourstep = 4;
int const componentcapacity = 256 / colourstep;
auto const redgreen = std::div( Index, componentcapacity * componentcapacity );
auto const greenblue = std::div( redgreen.rem, componentcapacity );
auto const blue = Index % componentcapacity;
return
glm::vec3 {
redgreen.quot * colourstep / 255.0f,
greenblue.quot * colourstep / 255.0f,
greenblue.rem * colourstep / 255.0f };
*/
// alternatively
return
glm::vec3{
( ( Index & 0xff0000 ) >> 16 ) / 255.0f,
@@ -2599,13 +2669,6 @@ opengl_renderer::pick_color( std::size_t const Index ) {
std::size_t
opengl_renderer::pick_index( glm::ivec3 const &Color ) {
/*
return (
std::floor( Color.b / 4 )
+ std::floor( Color.g / 4 ) * 64
+ std::floor( Color.r / 4 ) * 64 * 64 );
*/
// alternatively
return
Color.b
+ ( Color.g * 256 )

View File

@@ -237,9 +237,7 @@ private:
void
setup_drawing( bool const Alpha = false );
void
setup_shadow_map(opengl_texture &tex);
void
setup_shadow_color( glm::vec4 const &Shadowcolor );
setup_shadow_map(opengl_texture *tex);
void
setup_environment_light( TEnvironmentType const Environment = e_flat );
// runs jobs needed to generate graphics for specified render pass
@@ -401,6 +399,11 @@ private:
std::unique_ptr<opengl_texture> m_shadow_tex;
std::unique_ptr<gl::program> m_shadow_shader;
std::unique_ptr<gl::framebuffer> m_pick_fb;
std::unique_ptr<opengl_texture> m_pick_tex;
std::unique_ptr<gl::renderbuffer> m_pick_rb;
std::unique_ptr<gl::program> m_pick_shader;
material_handle m_invalid_material;
bool m_widelines_supported;

View File

@@ -12,12 +12,25 @@ uniform sampler2DShadow shadowmap;
float calc_shadow()
{
vec3 coords = f_light_pos.xyz;
//float bias = clamp(0.0025*tan(acos(clamp(dot(f_normal, -lights[0].dir), 0.0, 1.0))), 0, 0.01);
float bias = 0.0f;
vec3 coords = f_light_pos.xyz / f_light_pos.w;
float shadow = texture(shadowmap, vec3(coords.xy, coords.z - bias));
// do something better
float bias = 0.0001f;
//sampler PCF
//float shadow = texture(shadowmap, vec3(coords.xy, coords.z - bias));
//sampler PCF + PCF
float shadow = 0.0;
vec2 texel = 1.0 / textureSize(shadowmap, 0);
for (float y = -1.5; y <= 1.5; y += 1.0)
for (float x = -1.5; x <= 1.5; x += 1.0)
shadow += texture(shadowmap, coords.xyz + vec3(vec2(x, y) * texel, -bias));
shadow /= 16.0;
if (coords.z > 1.0f)
shadow = 1.0f;
return shadow;
}

8
shaders/pick.frag Normal file
View File

@@ -0,0 +1,8 @@
#version 330
#include <common>
void main()
{
gl_FragColor = vec4(param[0].rgb, 1.0);
}

10
shaders/pick.vert Normal file
View File

@@ -0,0 +1,10 @@
#version 330
layout(location = 0) in vec3 v_vert;
#include <common>
void main()
{
gl_Position = (projection * modelview) * vec4(v_vert, 1.0f);
}

View File

@@ -1078,14 +1078,9 @@ ui_layer::render_tooltip() {
glm::dvec2 mousepos;
glfwGetCursorPos( m_window, &mousepos.x, &mousepos.y );
ImGui::SetNextWindowPos(ImVec2(mousepos.x, mousepos.y));
ImGui::SetNextWindowSize(ImVec2(0, 0));
ImGui::Begin("Tooltip", nullptr,
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar |
ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoBringToFrontOnFocus);
ImGui::TextUnformatted(m_tooltip.c_str());
ImGui::End();
ImGui::BeginTooltip();
ImGui::TextUnformatted(m_tooltip.c_str());
ImGui::EndTooltip();
}
void