43

Deferred shading is only a technique to "defer" the actual shading operation for later stages, this can be great to reduce the number of passes needed (for example) to render 10 lights which needs 10 passes. My point is regardless of the rendering technique you are using there are certain possible rendering optimizations that reduce the number of objects (...


11

In deferred shading all the material properties are rendered into the G-buffer, e.g. albedo, normals, roughness, metalness, etc. that are needed for BRDF evaluation. After this step shading is performed for pixels within light volumes using light and material properties as input to the BRDF. The problem with deferred shading is that more complex BRDF's (e.g. ...


9

I understand that having the same "size" each attachment can be aligned better, but practically speaking is it better to waste channels (or reserve them for future use) and having all the RTs of the same size or I should use just what needed? Having a unified 32bit aligned Render Targets is better, even if it means "wasting" some memory. This will be ...


6

Your problem is not related to deferred shading whatsoever, you need to implement the basic core elements of a renderer before you try to speed up some specific part. When you have finished with what concept3d has explained, if you actually find that you need to optimize the deferred shader itself (as opposed to the whole rasterization pass) you can ...


6

Final answer, solved the performance problem! Changed my culling loop to this instead (based on the one used by Dice in BF3) uint threadCount = WORK_GROUP_SIZE * WORK_GROUP_SIZE; uint passCount = (numActiveLights + threadCount - 1) /threadCount; for (uint passIt = 0; passIt < passCount; ++passIt) { uint lightIndex = passIt * threadCount + ...


6

Update for Unity 5.5 See @TWickz's answer. TL;DR Add #define UNITY_BRDF_PBS BRDF2_Unity_PBS right before #pragma's and #define's in the shader. Finding the solution was time-consuming, but I gained useful knowledge and so will you if you follow my “investigation log” below. I hope it's suitable answer format in this case. Step 1 Tinkering with light....


5

Solution I used good algorithm for depth linearization but I didn't convert depth to NDC first: const float near = 0.1; // projection matrix's near plane const float far = 90.0; // projection matrix's far plane float LinearizeDepth(float depth) { float z = depth * 2.0 - 1.0; // back to NDC return (2.0 * near * far) / (far + near - z * (far - near))...


5

I found a solution that works well. I don't think it gets any faster than this. What I did first is, I did the matrix-vector multiply by manually and skipped all the matrix components which are zero. I used an inverse projection matrix for this (to transform to view space). That left me with this code: vec3 calculate_view_position(vec2 texture_coordinate,...


4

The draw order often implied by tutorials, where you do something like this: for each object: for each pass: apply pass state draw object is actually backwards from how it makes sense to do it in a "real game" context. Rather, you'd be more likely to do something like: for each pass: apply pass state for each object (grouped ...


4

The result sampled from gbuffer_texture[2] will be in the [0, 1] range, but in OpenGL, NDC space ranges from -1 to 1 along all three axes. (This is different from D3D, where the NDC space ranges from 0 to 1 along the z axis.) So, you need to multiply the depth result by 2 and subtract 1 to convert the range to [-1, 1], just as you're doing already for the ...


4

To me it looks very much like your issue here is that you are mixing world and viewspace or something similiar. Now your GBuffer normals look like they might be in viewspace in that picture, but the code in your geometry pass definitely doesn't transform them from world to view space. If they are in world space then your NBT matrix is basically oriented ...


4

Note that some of the functions used here have been deprecated in Unity 5.5, but I have tested it to work. In Unity 5.5, many changes have been made. The most significant, being that the dot product is now calculated on the fly, and the light.ndotl field is no longer taken into consideration anywhere in code. I spoke to the original author of the blog ...


3

Have solved the issue, partially. This is the new culling code, which works for everything but the far and near plane. Performance is still pretty bad so if anyone can see what might cause that it would be appreciated. ivec2 pixel = ivec2(gl_GlobalInvocationID.xy); vec4 normalColor = imageLoad(normalDepth, pixel); float d = normalColor.w; ...


3

I'd say 2-3 passes is pretty normal. I suspect 4 is not uncommon. For vertex-lit games, 1-2. Usually just the albedo pass then some post effect or another. For pixel lit, 3+ is going to be the norm. 1st pass is g-buffer, z-buffer, surface normals and diffuse/albedo info as you describe it. Building blocks. 2nd pass we try to fit all other ops, but in ...


3

Usually each post processing effect has it own pass unless the effects are "organically" coupled and/or are simple. For example, to simulate an old film camera, you could put the grayscale, sepia, noise, scratch and vignetting effects all inside the same shader, since each effect is a simple part of the goal effect. On the other hand, some other effects have ...


3

Branching incurs overhead on GPU if the threads take different branches, which leads to serialisation. Thus, if all of your pixels take the same conditional branch, the overhead is negligible. In addition, if the condition is complex, it can increase the number of registers used per thread which can impact performance depending on how much is this increment. ...


3

Your positions are converted from WCS ( World Coordinate System) to NDC (Normalized Device Coordinates) in order to by saved inside the depth buffer. This is achieved by multiplying your coordinates with the view matrix to convert them to ECS (Eye Coordinate System) and then with the projection matrix. And at last they are divided by W component in order to ...


3

It's going to depend on the hardware and app, of course, but on current generation GPUs (NVIDIA Kepler, AMD GCN), I believe there is no penalty for using different render target formats at once. On older GPUs you simply couldn't do it; all render targets had to be the same format. Writing out to multiple render targets is usually memory-bound, so you can ...


3

I've already found some time and solution to my problems and I want share it with you. Maybe it will help someone: float distFromCentroid=ACamera.far(); camera.setLookAt(frustum_centroid+dir->direction*distFromCentroid,frustum_centroid); for(int i=0;i<8;i++){ point[i]=ACamera._point[i]*camera.matrix; } min=point[0]; max=point[0]; for(int i=0;i&...


3

You can use any shader to fill the g-buffer, it doesn't have to be generic. That's not the point of deferred, the point of deferred is when you come to do the lighting pass you combine the various render targets in the g-buffer with your lights; your lighting pass is confined to pixels on-screen (rather than shading pixels which may be occluded). But it's ...


3

Well, it's not new and it's a proper method. I think a common term for this "color picking", at least that's what i call it. As long as you are fine with picking only one object at a time, and that object being the one on top, there are no critical shortcomings. Even multi-select clicks are possible to a certain extend by mixing/adding colors/ids. However,...


2

This is probably the issue: https://www.opengl.org/wiki/Framebuffer_Object#Feedback_Loops Using a texture that is currently bound to an FBO that is current bound as the rendering target is undefined. You must unbind the FBO before using the texture. You can leave the texture bound to the FBO so long as the FBO itself is unbound. You need to bind a 2nd FBO ...


2

Some things you can try: Don't use a separate position buffer. Instead reconstruct position from the depth buffer (bound as a texture). Use GL_RGB10_A2 for your normal buffer. This is two-third the size of GL_RGB16F and should provide enough accuracy. GL_RGBA8 should provide enough accuracy for your albedo buffer. It should be fairly quick to try different ...


2

To be correct, lighting calculations should be carried out separately for each surface contained in a pixel, then the results should be averaged. For instance, think about the silhouette edge of an object, which contains some samples from the object and some other samples from whatever's behind it. If you simply averaged the positions, normals, etc. of all ...


2

One thing you should avoid for sure is to query the uniform locations every frame with glGetUniformLocation. This might be hurting the performance a little bit. Cache the locations in any data structure of your choice or plain variables once the shader program is created. Also you've mentioned that for each light a fullscreen quad is drawn. This is likely ...


2

Each parameter necessary to the final color of a fragment must be saved in the so called "G-Buffer". So you would have one Render Target for each of those parameters: Diffuse, Specular, Normals, Position (or depth), UVs and so on. This is the reason why deferred rendering is so memory intensive. And, in my opinion, it is only viable if the hardware has ...


2

First, from the picture it seems that in fact your light is not a "directional" light but a spotlight because you are using perspective projection, not an orthographic one (If not, then it is just the picture :) ). It is just a little thing, it should work more-or less the same. The important thing is, you don't render the positions from the light's point ...


2

If I understand your question correctly, you are building and applying the shadow maps at the same time. You really do not want to do that. If you are smart about this, you can vary the frequency of shadow map updates and save massive amounts of memory bandwidth necessary to actually fill the shadow maps (e.g. if nothing in the world moves inside the light ...


Only top voted, non community-wiki answers of a minimum length are eligible