diff --git a/engine/gfx/metal/src/gfx_metal.mm b/engine/gfx/metal/src/gfx_metal.mm index 96b6205..0ff86cc 100755 --- a/engine/gfx/metal/src/gfx_metal.mm +++ b/engine/gfx/metal/src/gfx_metal.mm @@ -119,6 +119,15 @@ MTLSamplerMinMagFilter toFilter(GFXFilter filter) { } } +MTLWinding toWinding(GFXWindingMode mode) { + switch(mode) { + case GFXWindingMode::Clockwise: + return MTLWindingClockwise; + case GFXWindingMode::CounterClockwise: + return MTLWindingCounterClockwise; + } +} + bool GFXMetal::is_supported() { return true; } @@ -584,10 +593,11 @@ GFXPipeline* GFXMetal::create_graphics_pipeline(const GFXGraphicsPipelineCreateI pipeline->pushConstantIndex = binding.binding; } + pipeline->winding_mode = info.rasterization.winding_mode; + MTLDepthStencilDescriptor* depthStencil = [MTLDepthStencilDescriptor new]; if(info.depth.depth_mode != GFXDepthMode::None) { - //depthStencil.depthCompareFunction = info.depth.depth_mode == GFXDepthMode::LessOrEqual ? MTLCompareFunctionGreaterEqual : MTLCompareFunctionGreater; depthStencil.depthCompareFunction = info.depth.depth_mode == GFXDepthMode::LessOrEqual ? MTLCompareFunctionLessEqual : MTLCompareFunctionLess; depthStencil.depthWriteEnabled = true; } @@ -760,6 +770,7 @@ void GFXMetal::submit(GFXCommandBuffer* command_buffer, const int window) { [renderEncoder setDepthStencilState:currentPipeline->depthStencil]; [renderEncoder setCullMode:((GFXMetalPipeline*)command.data.set_pipeline.pipeline)->cullMode]; + [renderEncoder setFrontFacingWinding:toWinding(((GFXMetalPipeline*)command.data.set_pipeline.pipeline)->winding_mode)]; if(currentPipeline->renderWire) [renderEncoder setTriangleFillMode:MTLTriangleFillModeLines]; diff --git a/engine/gfx/metal/src/gfx_metal_pipeline.hpp b/engine/gfx/metal/src/gfx_metal_pipeline.hpp index 38a68f8..df2e9d0 100755 --- a/engine/gfx/metal/src/gfx_metal_pipeline.hpp +++ b/engine/gfx/metal/src/gfx_metal_pipeline.hpp @@ -13,7 +13,8 @@ public: MTLPrimitiveType primitiveType; MTLCullMode cullMode; - + GFXWindingMode winding_mode; + struct VertexStride { int location, stride; }; diff --git a/engine/gfx/public/gfx.hpp b/engine/gfx/public/gfx.hpp index 284e8b1..24fc018 100755 --- a/engine/gfx/public/gfx.hpp +++ b/engine/gfx/public/gfx.hpp @@ -88,6 +88,11 @@ enum class GFXCullingMode { None }; +enum class GFXWindingMode { + Clockwise, + CounterClockwise +}; + struct GFXVertexInput { int location = 0; int stride = 0; @@ -158,6 +163,8 @@ struct GFXGraphicsPipelineCreateInfo { GFXPolygonType polygon_type = GFXPolygonType::Fill; GFXCullingMode culling_mode = GFXCullingMode::None; + + GFXWindingMode winding_mode = GFXWindingMode::Clockwise; } rasterization; struct Blending { diff --git a/engine/math/include/transform.hpp b/engine/math/include/transform.hpp index 9945a1f..4177c2e 100755 --- a/engine/math/include/transform.hpp +++ b/engine/math/include/transform.hpp @@ -5,15 +5,11 @@ #include "quaternion.hpp" namespace transform { - /* - Produces a right-handed perspective matrix. - */ - Matrix4x4 perspective(const float fov, const float aspectRatio, const float zNear); + Matrix4x4 perspective(const float field_of_view, const float aspect, const float z_near, const float z_far); + Matrix4x4 infinite_perspective(const float field_of_view, const float aspect, const float z_near); + Matrix4x4 orthographic(float left, float right, float bottom, float top, float zNear, float zFar); - /* - Produces right-handed outputs. - */ Matrix4x4 look_at(const Vector3 eye, const Vector3 center, const Vector3 up); Quaternion quat_look_at(const Vector3 eye, const Vector3 center, const Vector3 up); diff --git a/engine/math/src/transform.cpp b/engine/math/src/transform.cpp index ab872cb..7e10998 100755 --- a/engine/math/src/transform.cpp +++ b/engine/math/src/transform.cpp @@ -4,19 +4,36 @@ #include "math.hpp" -Matrix4x4 transform::perspective(const float fov, const float aspect, const float zNear) { - const float range = tanf(fov / 2.0f) * zNear; +/* + These produce left-handed matrices. + Metal/DX12 are both NDC +y down. + */ +Matrix4x4 transform::perspective(const float field_of_view, const float aspect, const float z_near, const float z_far) { + const float tan_half_fov = tanf(field_of_view / 2.0f); + + Matrix4x4 result(0.0f); + result[0][0] = 1.0f / (aspect * tan_half_fov); + result[1][1] = 1.0f / tan_half_fov; + result[2][2] = z_far / (z_far - z_near); + result[2][3] = 1.0f; + result[3][2] = -(z_far * z_near) / (z_far - z_near); + + return result; +} + +Matrix4x4 transform::infinite_perspective(const float field_of_view, const float aspect, const float z_near) { + const float range = tanf(field_of_view / 2.0f) * z_near; const float left = -range * aspect; const float right = range * aspect; const float bottom = -range; const float top = range; Matrix4x4 result(0.0f); - result[0][0] = (2.0f * zNear) / (right - left); - result[1][1] = (2.0f * zNear) / (top - bottom); - result[2][2] = -1.0f; - result[2][3] = -1.0f; - result[3][2] = -2.0 * zNear; + result[0][0] = (2.0f * z_near) / (right - left); + result[1][1] = (2.0f * z_near) / (top - bottom); + result[2][2] = 1.0f; + result[2][3] = 1.0f; + result[3][2] = -2.0 * z_near; return result; } @@ -25,7 +42,7 @@ Matrix4x4 transform::orthographic(float left, float right, float bottom, float t Matrix4x4 result(1.0f); result[0][0] = 2.0f / (right - left); result[1][1] = 2.0f / (top - bottom); - result[2][2] = - 1.0f / (zFar - zNear); + result[2][2] = 1.0f / (zFar - zNear); result[3][0] = -(right + left) / (right - left); result[3][1] = -(top + bottom) / (top - bottom); result[3][2] = - zNear / (zFar - zNear); @@ -36,7 +53,7 @@ Matrix4x4 transform::orthographic(float left, float right, float bottom, float t Matrix4x4 transform::look_at(const Vector3 eye, const Vector3 center, const Vector3 up) { const Vector3 f = normalize(center - eye); const Vector3 s = normalize(cross(f, up)); - const Vector3 u = cross(s, f); + const Vector3 u = cross(f, s); Matrix4x4 result(1.0f); result[0][0] = s.x; @@ -45,12 +62,12 @@ Matrix4x4 transform::look_at(const Vector3 eye, const Vector3 center, const Vect result[0][1] = u.x; result[1][1] = u.y; result[2][1] = u.z; - result[0][2] = -f.x; - result[1][2] = -f.y; - result[2][2] = -f.z; + result[0][2] = f.x; + result[1][2] = f.y; + result[2][2] = f.z; result[3][0] = -dot(s, eye); result[3][1] = -dot(u, eye); - result[3][2] = dot(f, eye); + result[3][2] = -dot(f, eye); return result; } @@ -104,7 +121,7 @@ Quaternion transform::quat_look_at(const Vector3 eye, const Vector3 center, cons const Vector3 direction = normalize(center - eye); Matrix3x3 result(1.0f); - result[2] = -direction; + result[2] = direction; result[0] = cross(up, result[2]); result[1] = cross(result[2], result[0]); diff --git a/engine/renderer/include/renderer.hpp b/engine/renderer/include/renderer.hpp index d877a71..4999017 100755 --- a/engine/renderer/include/renderer.hpp +++ b/engine/renderer/include/renderer.hpp @@ -165,12 +165,6 @@ public: std::unique_ptr shadow_pass; std::unique_ptr scene_capture; - /* - This is applied to most framebuffer pass projection-view matrices. - For example, under Metal the y is flipped because the framebuffer sample coordinates are flipped. - */ - Matrix4x4 correction_matrix; - GFXTexture* dummyTexture = nullptr; GFXRenderPass* unormRenderPass = nullptr; GFXPipeline* renderToUnormTexturePipeline = nullptr; diff --git a/engine/renderer/src/renderer.cpp b/engine/renderer/src/renderer.cpp index 13e09f2..ada9da5 100755 --- a/engine/renderer/src/renderer.cpp +++ b/engine/renderer/src/renderer.cpp @@ -94,9 +94,6 @@ Renderer::Renderer(GFX* gfx, const bool enable_imgui) : gfx(gfx) { if(enable_imgui) addPass(); - if(gfx->required_context() == GFXContext::Metal) - correction_matrix[1][1] *= -1.0f; - createBRDF(); } @@ -242,7 +239,7 @@ void Renderer::render(Scene* scene, int index) { for(auto& [obj, camera] : cameras) { const int actual_width = render_extent.width / cameras.size(); - camera.perspective = transform::perspective(radians(camera.fov), static_cast(actual_width) / static_cast(render_extent.height), camera.near); + camera.perspective = transform::infinite_perspective(radians(camera.fov), static_cast(actual_width) / static_cast(render_extent.height), camera.near); camera.view = inverse(scene->get(obj).model); Viewport viewport = {}; @@ -354,7 +351,7 @@ void Renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj sceneInfo.options = Vector4(1, 0, 0, 0); sceneInfo.camPos = scene.get(camera_object).get_world_position(); sceneInfo.camPos.w = 2.0f * camera.near * std::tanf(camera.fov * 0.5f) * (static_cast(extent.width) / static_cast(extent.height)); - sceneInfo.vp = camera.perspective * correction_matrix * camera.view; + sceneInfo.vp = camera.perspective * camera.view; for(const auto [obj, light] : scene.get_all()) { SceneLight sl; @@ -472,7 +469,7 @@ void Renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj RenderScreenOptions options = {}; options.render_world = true; - options.mvp = camera.perspective * camera.view * correction_matrix * scene.get(obj).model; + options.mvp = camera.perspective * camera.view * scene.get(obj).model; render_screen(command_buffer, screen.screen, continuity, options); } @@ -483,7 +480,7 @@ void Renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj float aspect; } pc; - pc.view = matrix_from_quat(scene.get(camera_object).rotation) * correction_matrix; + pc.view = matrix_from_quat(scene.get(camera_object).rotation); pc.aspect = static_cast(extent.width) / static_cast(extent.height); for(const auto& [obj, light] : scene.get_all()) { @@ -702,8 +699,6 @@ void Renderer::create_mesh_pipeline(Material& material) { pipelineInfo.shaders.fragment_src = material_compiler.compile_material_fragment(material, false); // scene capture does not use IBL - pipelineInfo.rasterization.culling_mode = GFXCullingMode::Frontface; - material.capture_pipeline = material_compiler.create_static_pipeline(pipelineInfo, false, true); } diff --git a/engine/renderer/src/scenecapture.cpp b/engine/renderer/src/scenecapture.cpp index 7d1b736..d3d95e6 100755 --- a/engine/renderer/src/scenecapture.cpp +++ b/engine/renderer/src/scenecapture.cpp @@ -159,7 +159,7 @@ void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) { const Vector3 lightPos = scene->get(obj).get_world_position(); - const Matrix4x4 projection = transform::perspective(radians(90.0f), 1.0f, 0.1f); + const Matrix4x4 projection = transform::infinite_perspective(radians(90.0f), 1.0f, 0.1f); const Matrix4x4 model = transform::translate(Matrix4x4(), Vector3(-lightPos.x, -lightPos.y, -lightPos.z)); SceneInformation sceneInfo = {}; @@ -294,7 +294,6 @@ void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) { } pc; pc.view = skyTransforms[face]; - pc.view[3] = Vector4(0, 0, 0, 1); // zero out translation pc.aspect = 1.0f; for(auto& [obj, light] : scene->get_all()) { diff --git a/engine/renderer/src/shadowpass.cpp b/engine/renderer/src/shadowpass.cpp index 4b96a6e..1c7d068 100755 --- a/engine/renderer/src/shadowpass.cpp +++ b/engine/renderer/src/shadowpass.cpp @@ -193,9 +193,11 @@ void ShadowPass::render_sun(GFXCommandBuffer* command_buffer, Scene& scene, Obje const Matrix4x4 projection = transform::orthographic(-25.0f, 25.0f, -25.0f, 25.0f, 0.1f, 100.0f); const Matrix4x4 view = transform::look_at(lightPos, Vector3(0), Vector3(0, 1, 0)); - const Matrix4x4 realMVP = projection * engine->get_renderer()->correction_matrix * view; + const Matrix4x4 realMVP = projection * view; - scene.lightSpace = projection * view; + scene.lightSpace = projection; + scene.lightSpace[1][1] *= -1; + scene.lightSpace = scene.lightSpace * view; const auto frustum = normalize_frustum(extract_frustum(projection * view)); @@ -224,11 +226,13 @@ void ShadowPass::render_spot(GFXCommandBuffer* command_buffer, Scene& scene, Obj command_buffer->set_viewport(viewport); - const Matrix4x4 perspective = transform::perspective(radians(90.0f), 1.0f, 0.1f); + const Matrix4x4 perspective = transform::perspective(radians(90.0f), 1.0f, 0.1f, 100.0f); - const Matrix4x4 realMVP = perspective * engine->get_renderer()->correction_matrix * inverse(scene.get(light_object).model); + const Matrix4x4 realMVP = perspective * inverse(scene.get(light_object).model); - scene.spotLightSpaces[last_spot_light] = perspective * inverse(scene.get(light_object).model); + scene.spotLightSpaces[last_spot_light] = perspective; + scene.spotLightSpaces[last_spot_light][1][1] *= -1; + scene.spotLightSpaces[last_spot_light] = scene.spotLightSpaces[last_spot_light] * inverse(scene.get(light_object).model); const auto frustum = normalize_frustum(extract_frustum(perspective * inverse(scene.get(light_object).model))); @@ -267,12 +271,12 @@ void ShadowPass::render_point(GFXCommandBuffer* command_buffer, Scene& scene, Ob const Vector3 lightPos = scene.get(light_object).get_world_position(); - const Matrix4x4 projection = transform::perspective(radians(90.0f), 1.0f, 0.1f); - const Matrix4x4 model = transform::translate(Matrix4x4(), Vector3(-lightPos.x, -lightPos.y, -lightPos.z)); + const Matrix4x4 projection = transform::perspective(radians(90.0f), 1.0f, 0.1f, 100.0f); + const Matrix4x4 model = inverse(scene.get(light_object).model); const auto frustum = normalize_frustum(extract_frustum(projection * shadowTransforms[face] * model)); - render_meshes(command_buffer, scene, projection * engine->get_renderer()->correction_matrix * shadowTransforms[face], model, lightPos, Light::Type::Point, frustum); + render_meshes(command_buffer, scene, projection * shadowTransforms[face], model, lightPos, Light::Type::Point, frustum); command_buffer->copy_texture(offscreen_color_texture, render_options.shadow_resolution, render_options.shadow_resolution, scene.pointLightArray, face, last_point_light, 0); } @@ -315,8 +319,7 @@ void ShadowPass::create_pipelines() { pipelineInfo.render_pass = render_pass; pipelineInfo.depth.depth_mode = GFXDepthMode::LessOrEqual; - pipelineInfo.rasterization.culling_mode = GFXCullingMode::None; - + // sun { pipelineInfo.label = "Sun Shadow"; diff --git a/engine/renderer/src/smaapass.cpp b/engine/renderer/src/smaapass.cpp index b18ac75..e64ab14 100755 --- a/engine/renderer/src/smaapass.cpp +++ b/engine/renderer/src/smaapass.cpp @@ -31,7 +31,6 @@ void SMAAPass::render(GFXCommandBuffer* command_buffer) { } pc; pc.viewport = Vector4(1.0f / static_cast(extent.width), 1.0f / static_cast(extent.height), extent.width, extent.height); - pc.correction_matrix = engine->get_renderer()->correction_matrix; // edge { diff --git a/shaders/post.vert.glsl b/shaders/post.vert.glsl index 41aaa9f..1e069b2 100755 --- a/shaders/post.vert.glsl +++ b/shaders/post.vert.glsl @@ -20,6 +20,7 @@ layout(location = 1) out vec4 outOffset; void main() { outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); gl_Position = vec4(outUV * 2.0f + -1.0f, 0.0f, 1.0f); - + outUV.y = 1.0 - outUV.y; + SMAANeighborhoodBlendingVS(outUV, outOffset); } diff --git a/shaders/rendering.nocompile.glsl b/shaders/rendering.nocompile.glsl index 34c4054..e15eba6 100755 --- a/shaders/rendering.nocompile.glsl +++ b/shaders/rendering.nocompile.glsl @@ -110,7 +110,7 @@ float pcss_sun(const vec4 shadowCoords, float light_size_uv) { if(num_blockers < 1) return 1.0; - const float penumbraWidth = penumbra_size(shadowCoords.z, average_blocker_depth); + const float penumbraWidth = penumbra_size(-shadowCoords.z, average_blocker_depth); const float uvRadius = penumbraWidth * light_size_uv * 0.1 / shadowCoords.z; return pcf_sun(shadowCoords, uvRadius); @@ -163,7 +163,7 @@ void blocker_distance_spot(const vec3 shadowCoords, const int index, const float for(int i = 0; i < numBlockerSearchSamples; i++) { const float z = texture(sampler2DArray(spot_shadow, shadow_sampler), vec3(shadowCoords.xy + PoissonOffsets[i] * searchWidth, index)).r; - if(z > shadowCoords.z) { + if(z < shadowCoords.z) { blockerSum += z; blockers++; } @@ -179,7 +179,7 @@ float pcss_spot(const vec4 shadowCoords, const int index, float light_size_uv) { if(num_blockers < 1) return 1.0; - const float penumbraWidth = penumbra_size(shadowCoords.z, average_blocker_depth); + const float penumbraWidth = penumbra_size(-shadowCoords.z, average_blocker_depth); const float uvRadius = penumbraWidth * light_size_uv * 0.1 / shadowCoords.z; return pcf_spot(shadowCoords, index, uvRadius); @@ -196,18 +196,16 @@ ComputedLightInformation calculate_spot(Light light) { float shadow = 1.0; if(light.shadowsEnable.x == 1.0) { const vec4 shadowCoord = fragPostSpotLightSpace[last_spot_light] / fragPostSpotLightSpace[last_spot_light].w; - - if(shadowCoord.z > -1.0 && shadowCoord.z < 1.0) { + #ifdef SHADOW_FILTER_NONE shadow = (texture(sampler2DArray(spot_shadow, shadow_sampler), vec3(shadowCoord.xy, last_spot_light)).r < shadowCoord.z) ? 0.0 : 1.0; #endif #ifdef SHADOW_FILTER_PCF - shadow = pcf_spot(shadowCoord, last_spot_light, 0.1); + shadow = pcf_spot(shadowCoord, last_spot_light, 0.01); #endif #ifdef SHADOW_FILTER_PCSS shadow = pcss_spot(shadowCoord, last_spot_light, light.shadowsEnable.y); #endif - } last_spot_light++; } @@ -215,7 +213,7 @@ ComputedLightInformation calculate_spot(Light light) { const float inner_cutoff = light.colorSize.w + radians(5); const float outer_cutoff = light.colorSize.w; - const float theta = dot(light_info.direction, normalize(-light.directionPower.xyz)); + const float theta = dot(light_info.direction, normalize(light.directionPower.xyz)); const float epsilon = inner_cutoff - outer_cutoff; const float intensity = clamp((theta - outer_cutoff) / epsilon, 0.0, 1.0); @@ -263,7 +261,7 @@ float pcss_point(const vec3 shadowCoords, const int index, float light_size_uv) return 1.0; const float depth = length(shadowCoords); - const float penumbraWidth = penumbra_size(depth, average_blocker_depth); + const float penumbraWidth = penumbra_size(-depth, average_blocker_depth); const float uvRadius = penumbraWidth * light_size_uv; return pcf_point(shadowCoords, index, uvRadius); diff --git a/shaders/sky.frag.glsl b/shaders/sky.frag.glsl index d3a846f..3b3027a 100755 --- a/shaders/sky.frag.glsl +++ b/shaders/sky.frag.glsl @@ -14,7 +14,7 @@ vec3 sky_ray(const vec2 uv) { const float d = 0.5 / tan(sun_position_fov.w / 2.0); return normalize(vec3((uv.x - 0.5) * aspect, uv.y - 0.5, - -d)); + d)); } void main() { diff --git a/tools/common/src/commoneditor.cpp b/tools/common/src/commoneditor.cpp index ff9609e..a346284 100755 --- a/tools/common/src/commoneditor.cpp +++ b/tools/common/src/commoneditor.cpp @@ -131,8 +131,8 @@ void CommonEditor::update(float deltaTime) { platform::capture_mouse(willCaptureMouse); if(willCaptureMouse) { - yaw += engine->get_input()->get_value("lookX") * -50.0f * deltaTime; - pitch += engine->get_input()->get_value("lookY") * -50.0f * deltaTime; + yaw += engine->get_input()->get_value("lookX") * 50.0f * deltaTime; + pitch += engine->get_input()->get_value("lookY") * 50.0f * deltaTime; const float speed = 7.00f; @@ -146,7 +146,7 @@ void CommonEditor::update(float deltaTime) { auto [obj, cam] = engine->get_scene()->get_all()[0]; engine->get_scene()->get(obj).position += right * movX * speed * deltaTime; - engine->get_scene()->get(obj).position += forward * movY * speed * deltaTime; + engine->get_scene()->get(obj).position += forward * -movY * speed * deltaTime; engine->get_scene()->get(obj).rotation = angle_axis(yaw, Vector3(0, 1, 0)) * angle_axis(pitch, Vector3(1, 0, 0)); } @@ -933,7 +933,7 @@ GFXTexture* CommonEditor::generate_common_preview(Scene& scene, const Vector3 ca engine->update_scene(scene); - scene.get(camera).perspective = transform::perspective(radians(45.0f), 1.0f, 0.1f); + scene.get(camera).perspective = transform::infinite_perspective(radians(45.0f), 1.0f, 0.1f); scene.get(camera).view = inverse(scene.get(camera).model); auto renderer = engine->get_renderer(); diff --git a/tools/common/src/debugpass.cpp b/tools/common/src/debugpass.cpp index 91e7811..9a8280b 100755 --- a/tools/common/src/debugpass.cpp +++ b/tools/common/src/debugpass.cpp @@ -236,7 +236,7 @@ void DebugPass::render_scene(Scene& scene, GFXCommandBuffer* commandBuffer) { Vector4 color; }; - Matrix4x4 vp = camera.perspective * engine->get_renderer()->correction_matrix * camera.view; + Matrix4x4 vp = camera.perspective * camera.view; commandBuffer->set_pipeline(primitive_pipeline); @@ -519,7 +519,7 @@ void DebugPass::get_selected_object(int x, int y, std::functionget_renderer()->correction_matrix * camera.view * model; + pc.mvp = camera.perspective * camera.view * model; if(object.render_type == SelectableObject::RenderType::Sphere) pc.mvp = transform::scale(pc.mvp, Vector3(object.sphere_size)); @@ -541,17 +541,17 @@ void DebugPass::get_selected_object(int x, int y, std::functionget_gfx()->copy_texture(selectTexture, selectBuffer); - uint8_t* map = reinterpret_cast(engine->get_gfx()->get_buffer_contents(selectBuffer)); + uint8_t* mapped_texture = reinterpret_cast(engine->get_gfx()->get_buffer_contents(selectBuffer)); - int buf_pos = 4 * ((extent.height - y) * extent.width + x); // flipped for metal + const int buffer_position = 4 * (y * extent.width + x); - uint8_t a = map[buf_pos + 3]; + uint8_t a = mapped_texture[buffer_position + 3]; - int id = map[buf_pos] + - map[buf_pos + 1] * 256 + - map[buf_pos + 2] * 256*256; + const int id = mapped_texture[buffer_position] + + mapped_texture[buffer_position + 1] * 256 + + mapped_texture[buffer_position + 2] * 256*256; - engine->get_gfx()->release_buffer_contents(selectBuffer, map); + engine->get_gfx()->release_buffer_contents(selectBuffer, mapped_texture); if(a != 0) { callback(selectable_objects[id]);