• Advertisement
  • Popular Tags

  • Popular Now

  • Advertisement
  • Similar Content

    • By fleissi
      Hey guys!

      I'm new here and I recently started developing my own rendering engine. It's open source, based on OpenGL/DirectX and C++.
      The full source code is hosted on github:
      https://github.com/fleissna/flyEngine

      I would appreciate if people with experience in game development / engine desgin could take a look at my source code. I'm looking for honest, constructive criticism on how to improve the engine.
      I'm currently writing my master's thesis in computer science and in the recent year I've gone through all the basics about graphics programming, learned DirectX and OpenGL, read some articles on Nvidia GPU Gems, read books and integrated some of this stuff step by step into the engine.

      I know about the basics, but I feel like there is some missing link that I didn't get yet to merge all those little pieces together.

      Features I have so far:
      - Dynamic shader generation based on material properties
      - Dynamic sorting of meshes to be renderd based on shader and material
      - Rendering large amounts of static meshes
      - Hierarchical culling (detail + view frustum)
      - Limited support for dynamic (i.e. moving) meshes
      - Normal, Parallax and Relief Mapping implementations
      - Wind animations based on vertex displacement
      - A very basic integration of the Bullet physics engine
      - Procedural Grass generation
      - Some post processing effects (Depth of Field, Light Volumes, Screen Space Reflections, God Rays)
      - Caching mechanisms for textures, shaders, materials and meshes

      Features I would like to have:
      - Global illumination methods
      - Scalable physics
      - Occlusion culling
      - A nice procedural terrain generator
      - Scripting
      - Level Editing
      - Sound system
      - Optimization techniques

      Books I have so far:
      - Real-Time Rendering Third Edition
      - 3D Game Programming with DirectX 11
      - Vulkan Cookbook (not started yet)

      I hope you guys can take a look at my source code and if you're really motivated, feel free to contribute :-)
      There are some videos on youtube that demonstrate some of the features:
      Procedural grass on the GPU
      Procedural Terrain Engine
      Quadtree detail and view frustum culling

      The long term goal is to turn this into a commercial game engine. I'm aware that this is a very ambitious goal, but I'm sure it's possible if you work hard for it.

      Bye,

      Phil
    • By tj8146
      I have attached my project in a .zip file if you wish to run it for yourself.
      I am making a simple 2d top-down game and I am trying to run my code to see if my window creation is working and to see if my timer is also working with it. Every time I run it though I get errors. And when I fix those errors, more come, then the same errors keep appearing. I end up just going round in circles.  Is there anyone who could help with this? 
       
      Errors when I build my code:
      1>Renderer.cpp 1>c:\users\documents\opengl\game\game\renderer.h(15): error C2039: 'string': is not a member of 'std' 1>c:\program files (x86)\windows kits\10\include\10.0.16299.0\ucrt\stddef.h(18): note: see declaration of 'std' 1>c:\users\documents\opengl\game\game\renderer.h(15): error C2061: syntax error: identifier 'string' 1>c:\users\documents\opengl\game\game\renderer.cpp(28): error C2511: 'bool Game::Rendering::initialize(int,int,bool,std::string)': overloaded member function not found in 'Game::Rendering' 1>c:\users\documents\opengl\game\game\renderer.h(9): note: see declaration of 'Game::Rendering' 1>c:\users\documents\opengl\game\game\renderer.cpp(35): error C2597: illegal reference to non-static member 'Game::Rendering::window' 1>c:\users\documents\opengl\game\game\renderer.cpp(36): error C2597: illegal reference to non-static member 'Game::Rendering::window' 1>c:\users\documents\opengl\game\game\renderer.cpp(43): error C2597: illegal reference to non-static member 'Game::Rendering::window' 1>Done building project "Game.vcxproj" -- FAILED. ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========  
       
      Renderer.cpp
      #include <GL/glew.h> #include <GLFW/glfw3.h> #include "Renderer.h" #include "Timer.h" #include <iostream> namespace Game { GLFWwindow* window; /* Initialize the library */ Rendering::Rendering() { mClock = new Clock; } Rendering::~Rendering() { shutdown(); } bool Rendering::initialize(uint width, uint height, bool fullscreen, std::string window_title) { if (!glfwInit()) { return -1; } /* Create a windowed mode window and its OpenGL context */ window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL); if (!window) { glfwTerminate(); return -1; } /* Make the window's context current */ glfwMakeContextCurrent(window); glViewport(0, 0, (GLsizei)width, (GLsizei)height); glOrtho(0, (GLsizei)width, (GLsizei)height, 0, 1, -1); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glfwSwapInterval(1); glEnable(GL_SMOOTH); glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glDepthFunc(GL_LEQUAL); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glEnable(GL_TEXTURE_2D); glLoadIdentity(); return true; } bool Rendering::render() { /* Loop until the user closes the window */ if (!glfwWindowShouldClose(window)) return false; /* Render here */ mClock->reset(); glfwPollEvents(); if (mClock->step()) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glfwSwapBuffers(window); mClock->update(); } return true; } void Rendering::shutdown() { glfwDestroyWindow(window); glfwTerminate(); } GLFWwindow* Rendering::getCurrentWindow() { return window; } } Renderer.h
      #pragma once namespace Game { class Clock; class Rendering { public: Rendering(); ~Rendering(); bool initialize(uint width, uint height, bool fullscreen, std::string window_title = "Rendering window"); void shutdown(); bool render(); GLFWwindow* getCurrentWindow(); private: GLFWwindow * window; Clock* mClock; }; } Timer.cpp
      #include <GL/glew.h> #include <GLFW/glfw3.h> #include <time.h> #include "Timer.h" namespace Game { Clock::Clock() : mTicksPerSecond(50), mSkipTics(1000 / mTicksPerSecond), mMaxFrameSkip(10), mLoops(0) { mLastTick = tick(); } Clock::~Clock() { } bool Clock::step() { if (tick() > mLastTick && mLoops < mMaxFrameSkip) return true; return false; } void Clock::reset() { mLoops = 0; } void Clock::update() { mLastTick += mSkipTics; mLoops++; } clock_t Clock::tick() { return clock(); } } TImer.h
      #pragma once #include "Common.h" namespace Game { class Clock { public: Clock(); ~Clock(); void update(); bool step(); void reset(); clock_t tick(); private: uint mTicksPerSecond; ufloat mSkipTics; uint mMaxFrameSkip; uint mLoops; uint mLastTick; }; } Common.h
      #pragma once #include <cstdio> #include <cstdlib> #include <ctime> #include <cstring> #include <cmath> #include <iostream> namespace Game { typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; typedef unsigned long ulong; typedef float ufloat; }  
      Game.zip
    • By lxjk
      Hi guys,
      There are many ways to do light culling in tile-based shading. I've been playing with this idea for a while, and just want to throw it out there.
      Because tile frustums are general small compared to light radius, I tried using cone test to reduce false positives introduced by commonly used sphere-frustum test.
      On top of that, I use distance to camera rather than depth for near/far test (aka. sliced by spheres).
      This method can be naturally extended to clustered light culling as well.
      The following image shows the general ideas

       
      Performance-wise I get around 15% improvement over sphere-frustum test. You can also see how a single light performs as the following: from left to right (1) standard rendering of a point light; then tiles passed the test of (2) sphere-frustum test; (3) cone test; (4) spherical-sliced cone test
       

       
      I put the details in my blog post (https://lxjk.github.io/2018/03/25/Improve-Tile-based-Light-Culling-with-Spherical-sliced-Cone.html), GLSL source code included!
       
      Eric
    • By Fadey Duh
      Good evening everyone!

      I was wondering if there is something equivalent of  GL_NV_blend_equation_advanced for AMD?
      Basically I'm trying to find more compatible version of it.

      Thank you!
    • By Jens Eckervogt
      Hello guys, 
       
      Please tell me! 
      How do I know? Why does wavefront not show for me?
      I already checked I have non errors yet.
      using OpenTK; using System.Collections.Generic; using System.IO; using System.Text; namespace Tutorial_08.net.sourceskyboxer { public class WaveFrontLoader { private static List<Vector3> inPositions; private static List<Vector2> inTexcoords; private static List<Vector3> inNormals; private static List<float> positions; private static List<float> texcoords; private static List<int> indices; public static RawModel LoadObjModel(string filename, Loader loader) { inPositions = new List<Vector3>(); inTexcoords = new List<Vector2>(); inNormals = new List<Vector3>(); positions = new List<float>(); texcoords = new List<float>(); indices = new List<int>(); int nextIdx = 0; using (var reader = new StreamReader(File.Open("Contents/" + filename + ".obj", FileMode.Open), Encoding.UTF8)) { string line = reader.ReadLine(); int i = reader.Read(); while (true) { string[] currentLine = line.Split(); if (currentLine[0] == "v") { Vector3 pos = new Vector3(float.Parse(currentLine[1]), float.Parse(currentLine[2]), float.Parse(currentLine[3])); inPositions.Add(pos); if (currentLine[1] == "t") { Vector2 tex = new Vector2(float.Parse(currentLine[1]), float.Parse(currentLine[2])); inTexcoords.Add(tex); } if (currentLine[1] == "n") { Vector3 nom = new Vector3(float.Parse(currentLine[1]), float.Parse(currentLine[2]), float.Parse(currentLine[3])); inNormals.Add(nom); } } if (currentLine[0] == "f") { Vector3 pos = inPositions[0]; positions.Add(pos.X); positions.Add(pos.Y); positions.Add(pos.Z); Vector2 tc = inTexcoords[0]; texcoords.Add(tc.X); texcoords.Add(tc.Y); indices.Add(nextIdx); ++nextIdx; } reader.Close(); return loader.loadToVAO(positions.ToArray(), texcoords.ToArray(), indices.ToArray()); } } } } } And It have tried other method but it can't show for me.  I am mad now. Because any OpenTK developers won't help me.
      Please help me how do I fix.

      And my download (mega.nz) should it is original but I tried no success...
      - Add blend source and png file here I have tried tried,.....  
       
      PS: Why is our community not active? I wait very longer. Stop to lie me!
      Thanks !
  • Advertisement
  • Advertisement
Sign in to follow this  

OpenGL Calculate depth of front sphere from back side

Recommended Posts

Currently sitting on an issue which i can't solve due to my lack of mathematical knowledge.

Here is a picture i made which sums up what i'm trying to do:

depthissue.png

 

To put it simply:

I render spheres (simple 3D meshes) into the scene on a seperate FBO by using frontface culling (so that the backside is rendered. The red part of the sphere on the screenshot.)

Now, in the fragment shader i can access the depth value of the rendered pixel by using "gl_Fragcoord.z". Now what i want to do is to calculate the depth value of the front facing side of the sphere of the exact same pixel. (so that i have a min and max depth value in order to know what the start depth and end depth value of the sphere on the given pixel is.) I need those values for post processing purposes.

 

My attempt to solve this was:

  1.  pass the current vertex position into the fragment shader
  2. subtract the vertex position from the origin point (in view space) to retrieve a normal pointing from the origin to the backface point
  3. Mirror the z-component of this normal (as we are in view space)
  4. add the mirrored normal to the origin point which gives us the front facing (vertex) position of the sphere
  5. use this position to calculate the depth value like in an openGL depth buffer. (haven't done this properly.)

depthissue2.png

 

I may or may not have an error in my shader code. (Maybe the way i multiply matrices is wrong?)

Here is my current code (a bit messy but i tried to comment it.)

//-------------- Vertex Shader --------------------
#version 330

layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec4 color;
layout (location = 3) in vec2 uv;
 
uniform mat4 uProjectionMatrix;
uniform mat4 uModelViewMatrix;

out vec4 oColor;
out vec2 vTexcoord;

out vec4 vFragWorldPos;
out vec4 vOriginWorldPos;
out mat4 vProjectionMatrix;

void main()
{
    oColor = color;
	vTexcoord = uv;

	//coordinates are in view space!
	vec4 tFragWorldPos = (uModelViewMatrix * vec4(position,1.0));
	vec4 tOriginWorldPos = (uModelViewMatrix * vec4(0.0,0.0,0.0,1.0));
	

	vFragWorldPos = (uModelViewMatrix * vec4(position,1.0));
	vOriginWorldPos = (uModelViewMatrix * vec4(0.0,0.0,0.0,1.0));
	
    gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(position,1.0);
	
	//send projection matrix to the fragment shader
	vProjectionMatrix = uProjectionMatrix;
}
//---------------- Fragment Shader --------------
#version 330
 
in vec4 oColor;
in vec2 vTexcoord;
out vec4 outputF;
in vec4 gl_FragCoord;


uniform sampler2D sGeometryDepth;
in vec4 gl_FragCoord;

in vec4 vFragWorldPos;
in vec4 vOriginWorldPos;
in mat4 vProjectionMatrix;


 
void main()
{

	//get texture coordinates of the screenspace depthbuffer
	vec2 relativeTexCoord = vec2(gl_FragCoord.x,gl_FragCoord.y);
	relativeTexCoord = relativeTexCoord-0.5+1.0;
	relativeTexCoord.x = relativeTexCoord.x/1280.0;
	relativeTexCoord.y = relativeTexCoord.y/720.0;
	

	//depth
	float backDepth = gl_FragCoord.z;//back depth
	float geometryDepth = texture2D(sGeometryDepth,relativeTexCoord).r;//geometry depth
	
	
	//--------------- Calculation of front depth---------------
	
	//get distance from origin to the fragment (normal in viewspace)
	vec3 offsetNormal = (vFragWorldPos/vFragWorldPos.w).xyz-(vOriginWorldPos/vOriginWorldPos.w).xyz;
	
	//mirror depth normal (z)
	offsetNormal.z*=-1.0;
	
	//add normal to origin point in order to get the mirrored coordinate point of the sphere
	vec4 sphereMirrorPos = vOriginWorldPos;
	sphereMirrorPos.xyz += offsetNormal.xyz;
	
	//apply perspective calculation
	vec4 projectedMirrorPos = vProjectionMatrix * sphereMirrorPos;
	projectedMirrorPos/=projectedMirrorPos.w;
	
	
	
	//TODO: CALCULATE PROPERLY
	float frontDepth = projectedMirrorPos.z * 0.5 + 0.5; // no idea what do do here further

	
	//want to color only the pixels where the scene depth (provided by a screen space texture which is a depthbuffer of a different FBO)
	//is exactly in between the min/max depth values of the sphere
	if(backDepth>geometryDepth && frontDepth<geometryDepth){
		outputF = vec4(1.0,1.0,1.0,1.0);
	}else{
		discard;
	}
	
	
}

 

I suspect that maybe transforming the coordinates into viewspace in the vertex shader (and working with those coordinates) may be an issue. (No idea where/when to divide by "W" for example.) Also i'm currently stuck at the part where i have to calculate the depth values in the same range as the OpenGL depth buffer in order to compare them in the if statement shown at the end of the fragment shader.

Hints/help would be greatly appreciated. 

Edited by Lewa

Share this post


Link to post
Share on other sites
Advertisement

I nearly got it working.

But there still seems to be a minor error in the calculation of the mirrored depth value.

Here is the current fragment shader (vertex shader is the same as above:)

#version 330
 
in vec4 oColor;
in vec2 vTexcoord;
out vec4 outputF;
in vec4 gl_FragCoord;


uniform sampler2D sGeometryDepth;
in vec4 gl_FragCoord;

in vec4 vFragWorldPos;
in vec4 vOriginWorldPos;
in mat4 vProjectionMatrix;

float linearizeDepth(float depthVal,float zNear,float zFar)
{
  float n = zNear; // camera z near
  float f = zFar; // camera z far
  float z = depthVal;
  return (2.0 * n) / (f + n - z * (f - n));	
}

void main()
{
	float uZnear = 0.01;
	float uZfar = 500.0;


	//get texture coordinates of the screenspace depthbuffer
	vec2 relativeTexCoord = vec2(gl_FragCoord.x,gl_FragCoord.y);
	relativeTexCoord = relativeTexCoord-0.5+1.0;
	relativeTexCoord.x = relativeTexCoord.x/1280.0;
	relativeTexCoord.y = relativeTexCoord.y/720.0;
	
	
	//depth of the backfacing sphere pixels and of the level geometry (depth texture of different FBO)
	float backDepth = linearizeDepth(gl_FragCoord.z,uZnear,uZfar);//back depth
	float geometryDepth = linearizeDepth(texture2D(sGeometryDepth,relativeTexCoord).r,uZnear,uZfar);//geometry depth
	
    //Now we have to calculate the front depth

	//--------------- Calculation of front depth---------------
	
	//get distance from origin to the fragment (in viewspace)
	
	float depthDiff = (vFragWorldPos.z-vOriginWorldPos.z);
	
	//substract depth difference from origin point in order to get the mirrored coordinate point of the sphere
	vec4 sphereMirrorPos = vec4(vFragWorldPos.xy,vOriginWorldPos.z - depthDiff,vOriginWorldPos.w);

	//apply perspective calculation
	vec4 projectedMirrorPos = vProjectionMatrix * sphereMirrorPos;
	projectedMirrorPos/=projectedMirrorPos.w;
	
	
	//depth calculation
	float frontDepth = (projectedMirrorPos.z + 1.0) / 2.0;
	frontDepth = linearizeDepth(frontDepth,uZnear,uZfar);
	

	//want to color only the pixels where the scene depth (provided by a screen space texture which is a depthbuffer of a different FBO)
	//is exactly in between the min/max depth values of the sphere
	
	if(backDepth>geometryDepth && frontDepth<geometryDepth){
		outputF = vec4(1.0,1.0,1.0,1.0);
	}else{
		discard;
	}
	

	
}

 

I believe the issue is somewhere here:

float depthDiff = (vFragWorldPos.z-vOriginWorldPos.z);
	
//add normal to origin point in order to get the mirrored coordinate point of the sphere
vec4 sphereMirrorPos = vec4(vFragWorldPos.xy,vOriginWorldPos.z - depthDiff,vOriginWorldPos.w);

"vFragWorldPos" is the position of the current vertex in ModelviewSpace. "vOriginWorldPos" is the origin of the sphere in modelviewSpace.

I simply calculate the z difference of both points by substracting the z components of both vectors.

Then i reconstruct the mirrored vertex coordinate by using the xy coordiantes of "vFragWorldPos" while the z-coordinate is calculated by substracting the depthDifference from the origin z-coordinate.

 

The issue is that it doesn't seem to give correct results by doing so.

I tested if this reconstruction method by changing this line:

vec4 sphereMirrorPos = vec4(vFragWorldPos.xy,vOriginWorldPos.z - depthDiff,vOriginWorldPos.w);

to this:

vec4 sphereMirrorPos = vec4(vFragWorldPos.xy,vOriginWorldPos.z + depthDiff,vOriginWorldPos.w);

which effectively calculates the depth of the back side of the sphere which i then compared with the values of the depth buffer. They are exactly the same. (which is correct.) But substracting the depthDiff value doesn't yield correct results.

 

Is there something that i'm missing? Maybe the z coordinates of the vertices which were transformed to modelview space aren't linear?

 

Edited by Lewa

Share this post


Link to post
Share on other sites

This sounds like an XY problem to me. Try backing up a step or two and describe what you're trying to accomplish. I suspect someone on these forums will be able to suggest a different approach that might work better.

Share this post


Link to post
Share on other sites

I only looked over the code quickly, so apologies if I'm misunderstanding something.  But, assuming your description of how you're trying to go about solving this, and that you're doing all the math in view space as you said... then it wont work because negating the z value wont give you what you think it gives you.  It wont give you a point backwards along the line of sight.

You can solve this by getting the point of intersection between the line of sight to the pixel and the line from the sphere origin that intersects that line at a right angle.  Once you get this point (lets call it midPoint) you're basically home free as you can just use the pixel position and midPoint to get the point your looking for.

Here's some pseudo code:

vec3 pixelPos;	// position in view space of the pixel on the sphere back face.  Known.
vec3 spherePos;	// position in view space of sphere origin.  Known.

vec3 tempDir = CrossProduct(spherePos, pixelPos);	// vector pointing up/down from plane
tempDir = CrossProduct(pixelPos, tempDir);		// vector pointing from line-of-sight towards spherePos
tempDir = Normalize(tempDir);

float d = DotProduct(tempDir, spherePos);	// distance along the "right" vector towards the sphere origin

vec3 midPoint = spherePos - tempDir * d;	// midPoint = point midway from front to backface along ling-of-sight

vec3 frontFacePos = 2 * midPoint - pixelPos;	// the frontface view-space point you want

Of course this code doesnt check to see if pixelPos and spherePos are parallel.  You'll need to check for that and handle the situation accordingly.  But, I think this will give you what you want... a point backwards along the line of sight (in view-space) from the backface of the sphere towards the frontface.

Share this post


Link to post
Share on other sites
On 7.08.2017 at 11:51 AM, 0r0d said:

I only looked over the code quickly, so apologies if I'm misunderstanding something.  But, assuming your description of how you're trying to go about solving this, and that you're doing all the math in view space as you said... then it wont work because negating the z value wont give you what you think it gives you.  It wont give you a point backwards along the line of sight.

You can solve this by getting the point of intersection between the line of sight to the pixel and the line from the sphere origin that intersects that line at a right angle.  Once you get this point (lets call it midPoint) you're basically home free as you can just use the pixel position and midPoint to get the point your looking for.

Here's some pseudo code:


vec3 pixelPos;	// position in view space of the pixel on the sphere back face.  Known.
vec3 spherePos;	// position in view space of sphere origin.  Known.

vec3 tempDir = CrossProduct(spherePos, pixelPos);	// vector pointing up/down from plane
tempDir = CrossProduct(pixelPos, tempDir);		// vector pointing from line-of-sight towards spherePos
tempDir = Normalize(tempDir);

float d = DotProduct(tempDir, spherePos);	// distance along the "right" vector towards the sphere origin

vec3 midPoint = spherePos - tempDir * d;	// midPoint = point midway from front to backface along ling-of-sight

vec3 frontFacePos = 2 * midPoint - pixelPos;	// the frontface view-space point you want

Of course this code doesnt check to see if pixelPos and spherePos are parallel.  You'll need to check for that and handle the situation accordingly.  But, I think this will give you what you want... a point backwards along the line of sight (in view-space) from the backface of the sphere towards the frontface.

That is EXACTLY what i needed/what i was looking for. Thank you!

Although i'm having a hard time understanding why this formula works. (As i seem to misunderstand how the viewspace works.)

Quote

Of course this code doesnt check to see if pixelPos and spherePos are parallel.

What exactly do you mean with "parallel"? If they are axis aligned in view space?

Edited by Lewa

Share this post


Link to post
Share on other sites
6 hours ago, Lewa said:

That is EXACTLY what i needed/what i was looking for. Thank you!

Although i'm having a hard time understanding why this formula works. (As i seem to misunderstand how the viewspace works.)

What exactly do you mean with "parallel"? If they are axis aligned in view space?

Here's a diagram that might help:

Untitled-1.thumb.jpg.02ffe96245f5107f535fe1c5c9e6e9a2.jpg

I think the problem is that you're thinking that view space means the Z values point along the line of sight to the camera.  But, view space is just camera space.  So when you take the vector (=> pixelPos - spherePos) and then negate the Z component, you get the "incorrect midPoint" seen above.  

So what you need is to find the correct midPoint by first finding the "tempDir" in the image, which is found by first finding the vector normal to the plane and then doing a cross product to find this new vector which is orthogonal to both the plane normal and the line of sight vector.  Once you have that vector you easily get the midPoint and then easily the frontFacePos.

Does that make sense?

As far as why it matters to check if spherePos and pixelPos are parallel... if they are parallel (ie they both lie on the line from camera to spherePos) then the first 2 cross products will give you a 0 length vector, and then the normalize operation will cause a divide by 0.  So, you need to check if the pixelPos is parallel to spherePos, in which case the frontFacePos would just be

frontFacePos = 2 * spherePos - pixelPos;

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Advertisement