• Advertisement

matt77hias

Member
  • Content count

    692
  • Joined

  • Last visited

Community Reputation

528 Good

About matt77hias

  • Rank
    Advanced Member

Personal Information

Social

  • Twitter
    matt77hias
  • Github
    matt77hias

Recent Profile Visitors

11492 profile views
  1. DX12 Shader compile step

    Ideally the shader type should be part of the extension. I use a separate project and reuse property sheets, but I still have a very large .vcxproj file, since I cannot reuse or deduce the shader types. So all shader files are mentioned for all configurations. When browsing the file extensions that will be opened with Visual Studio, I noticed .vs, .hs, .ds, .gs, .ps and .cs. But since Visual Studio does not offer these from inside the IDE, I wonder if this is somehow deprecated (is it actually ever used?).
  2. Lighting space

    Idd. Though, on the other hand, you can apply light culling per camera. Furthermore, shadow maps, tiling and clustering need to be re-generated anyway per camera. But I was already convinced (Though, I would like to have rather woke up instead of gone to sleep with this idea at the prospect of the many refactorings waiting ahead ) An indirection with a light index list (tiled and clustered shading) makes actually lots of sense. You just need to regenerate the index list. Without an index list, you need to remove the culled lights. (Note that this is a funny aspect of gamedev.net: I have a quote to myself in the same post )
  3. Lighting space

    Correct me if I am wrong (since I haven't worked with all of them) but I found on the web that Unity3D, Unreal Engine 4 and CryEngine 3 all perform shading in world space. Blender uses camera space, but has an explicit option to switch to world space shading to be compatible with other engines. Also, camera space can be better for compressing normals in the GBuffer since all normals face the camera. On the other hand, you can probably see flickering specular highlights when using camera space. World space seems somehow by default temporally more coherent and robust.
  4. Lighting space

    Oh yeah missed that one. Though, I currently use this to apply tangent-space normal mapping (with the surface normal in view space). Though, without pre-computation; just on the fly in the PS. Currently, I have a separate object-to-camera and camera-to-projection inside my vertex shader. But if I am going to switch, object-to-world and world-to-projection are the "obvious" replacements. Though for precision, I best leave the camera-to-projection separately. So then I am back at the object-to-world, world-to-camera, camera-to-projection chain What do you advise for the typical gamma of "Unity3D-kind-of" games? All my code uses camera space, though I become tempted to use world space (which can also easier be changed later on to offset-world-space, I guess)? Especially, the reduction in map/unmap invocations seems like a holy grail at the moment. Not that I experience any bottlenecks so far, but it still seems wasteful in case of multiple passes.
  5. Nah, I wouldn't call it premature optimization, since the actual decision in both cases can have a large impact on the code base. I mean, one should think things through at a certain level before coding instead of rushing off and pushing your feet at every stone on the way. Of course, if you want to foresee everything in advance, you won't have written down a single line of code by the end of the day. On the other hand, continuous refactoring when the problems start to appear is wasteful as well, since refactoring by itself does not result in added value. So just find a balance between designing (standing still) and coding (moving forward)
  6. Lighting space

    From a theoretical point of view, it does not really matter in which space, or coordinate system, you evaluate the rendering equation. Without introducing artificial spaces, you can chose among object, world, camera and light spaces. Since the number of objects and lights in typical scenes is way larger than the number of cameras, object and light spaces can be skipped. If you selected object space, all the lights (of which the number of lights is dynamic) need to be transformed to object space in the pixel shader. If you selected light space, all objects need to be transformed to each light space in the pixel shader. Both cases, clearly waste precious resources on "useless" transformations on a per fragment level. So world and camera space remain. Starting with a single camera in the scene, camera space seemed the most natural choice. Lights can be transformed just once in advance. Objects can be transformed inside the vertex shader (on a per vertex level). Furthermore, positions in camera space are always equal to the inverse lighting direction used in BRDFs. So no offsetting calculations need to be performed, since the camera will always be located at the origin in its own space. Given that you can use multiple cameras, each having its own viewport, the process repeats itself, but now for a different camera space. The data used in the shaders must be updated accordingly. For example: the object-to-camera transformation matrix should reflect the right camera. This implies many map/unmap invocations for object data. If however, lighting is performed in world instead of camera space, I could just allocate a constant buffer per object and update all the object data once per frame and bind it multiple times in case of multiple passes. Finally given my current and possible future voxelization problems, world space seems more efficient than camera space. It is possible to use a hybrid of camera and world space, but this will involve many "useless" transforms back and forth, so I rather stick to one space. Given all this, I wonder if camera space is still appealing? Even for LOD purposes, length(p_view) and length(p_world - eye_world) are pretty much equivalent with regard to performance.
  7. This can be really advantageous given that you have quite some data stored at the vertices. Currently, DirectXTK only uses a position, color and pair of texture coordinates per vertex for sprites, which is pretty match the equivalent of a single transformation matrix.
  8. In a very basic setting, your sprites will contain opaque and transparent fragments (e.g. text). These transparent fragments need to be blended correctly with the fragments behind them to "leak" the correct background. This can be achieved with the depth buffer in at least two separate passes for one layer of transparency (you can use more passes for multiple layers you want to support on top of each other as well). Alternatively, you can sort the sprites on the CPU, while only requiring a single pass when rendering the sprites in order (based on the sorting). For transparent 3D objects, you can use the depth buffer as well, but CPU sorting is not guaranteed to be possible in all cases. You can have interlocked transparent triangles, for example, which cannot be sorted once for the whole image, but should rather be sorted per pixel. Sprites, on the other hand, are just stacked on top of each other. So you can always sort once for the whole image, instead of per pixel, allowing CPU sorting in all cases. So given the above, I would say to carefully profile the GPU depth buffer approach for sprites, because I expect the CPU sorting to be faster for a common load of sprites. Even if you have an extreme number of sprites, you can always rely on insertion sort based sorting algorithms while exploiting coherency between frames.
  9. Voxelization cracks

    The voxels are occupied. Though, the filled voxels for a single plane occur in multiple consecutive slices (due to the slope of the plane) I guess that the values stored in the voxels can indeed start fluctuating while moving and changing the camera orientation. Thought, indirect illumination is generally much smoother and low-frequency than direct illumination. But I am curious at the final results too. For the current debug visualization, the popping is quite strange, since it becomes black. I wouldn't be surprised when the color changes, but black, however, indicates that the voxel is empty.
  10. Voxelization cracks

    I think it is possible to step over a voxel, since I just use one sample for the visualization (i.e. no marching based on opacity). But I basically use the same calculations and data for calculating the indices during the voxelization and visualization passes. Voxelization PS // Valid range: [-R/2,R/2]x[R/2,-R/2]x[-R/2,R/2] const float3 voxel = input.p_view * g_voxel_inv_size * float3(1.0f, -1.0f, 1.0f); // Valid range: [0,R)x(R,0]x[0,R) const int3 s_index = floor(voxel + 0.5f * g_voxel_grid_resolution); const uint3 index = (uint3)s_index; [branch] if (any(s_index < 0 || index >= g_voxel_grid_resolution)) { return; } ... const uint flat_index = FlattenIndex(index, g_voxel_grid_resolution); Voxelization to Texture CS [branch] if (any(thread_id >= g_voxel_grid_resolution)) { return; } const uint flat_index = FlattenIndex(thread_id, g_voxel_grid_resolution); ... voxel_texture[thread_id] = ...; Visualization PS // Valid range: [-R/2,R/2]x[R/2,-R/2]x[-R/2,R/2] const float3 voxel = p * g_voxel_inv_size * float3(1.0f, -1.0f, 1.0f); // Valid range: [0,R)x(R,0]x[0,R) const int3 s_index = floor(voxel + 0.5f * g_voxel_grid_resolution); return g_voxel_texture[s_index].xyz; It is not incomplete and covers more than the "screen space" of the lighting. It is basically just the same as world space voxelization, only the rotation of your grid will be based on the camera orientation and the camera will always occupy the center voxel. So you will not favor certain directions more or less when calculating the indirect illumination contribution.
  11. Voxelization cracks

    I want to avoid cracks (how ironic looking at my renderings) in the voxelization of solid triangles. You can always get cracks independent of your coordinate system. Therefore, I select the most detailed rasterization out of the three primary axes inside the GS. https://developer.nvidia.com/content/basics-gpu-voxelization Like clustered shading for light sources (i.e. generate the depth map, calculate the max depths per tile and create n equidistant bins for each tile based on the max depth of that tile)? Currently, I just want to try the easiest approach: regular grid (i.e. the same equidistant bins everywhere). It is also easier to transfer the voxel data from a structured buffer, representing a regular 3D grid, to a 3D texture.
  12. Voxelization cracks

    My voxelization is constructed in view space, not in world space. I evaluate the rendering equation in view space as well. So I can avoid some extra transforms this way. Furthermore, I will eventually use a clip map (sort of cascaded grid) instead of a regular grid, which is for lod purposes better and easier when centered around the camera. This explains the dependence on the camera angles and especially the x axis, which changes the slope of the ground plane with regard to the camera. I do not really use an explicit projection matrix while voxelizing on the GPU. I use an explicit orthographic projection matrix on the CPU for view frustum culling before voxelization and an implicit orthographic projection matrix in this geometry shader. The visualization is another pass that converts the view space position in a similar way as the voxelization pass to retrieve a location inside a 3D texture. So this is merely just for debugging (no cone tracing and thus no ray marching, just one texture sample).
  13. [maxvertexcount(3)] void GS(triangle GSInputPositionNormalTexture input[3], inout TriangleStream< PSInputPositionNormalTexture > output_stream) { const float3 abs_n = abs(cross(input[1].p_view - input[0].p_view, input[2].p_view - input[0].p_view)); const uint dir_xy = (abs_n.x > abs_n.y) ? 0u : 1u; const uint dir = (abs_n.z > abs_n[dir_xy]) ? 2u : dir_xy; PSInputPositionNormalTexture output[3]; // Project the triangle in the dominant direction for rasterization (p), // but not for lighting (p_view). [unroll] for (uint i = 0u; i < 3u; ++i) { [flatten] switch (dir) { case 0u: output[i].p.xy = input[i].p_view.yz; break; case 1u: output[i].p.xy = input[i].p_view.zx; break; default: output[i].p.xy = input[i].p_view.xy; break; } // [m_view] * [voxels/m_view] -> [voxels] output[i].p.xy *= g_voxel_inv_size; ... } // For each projected triangle, a slightly larger bounding triangle ensures // that any projected triangle touching a pixel will necessarily touch the // center of this pixel and thus will get a fragment emitted by the rasterizer. const float2 delta_10 = normalize(output[1].p.xy - output[0].p.xy); const float2 delta_21 = normalize(output[2].p.xy - output[1].p.xy); const float2 delta_02 = normalize(output[0].p.xy - output[2].p.xy); // [voxels] * [2 m_ndc/voxels] -> [-1,1] const float voxel_to_ndc = 2.0f * g_voxel_grid_inv_resolution; // Move vertices for conservative rasterization. output[0].p.xy = (output[0].p.xy + normalize(delta_02 - delta_10)) * voxel_to_ndc; output[1].p.xy = (output[1].p.xy + normalize(delta_10 - delta_21)) * voxel_to_ndc; output[2].p.xy = (output[2].p.xy + normalize(delta_21 - delta_02)) * voxel_to_ndc; ... } I tried to voxelize the scene into a regular 3D voxel grid centered around the camera. This results in some odd cutouts and temporal disappearances of triangles which seems to dependent on the camera angles. With conservative rasterization: output[0].p.xy = (output[0].p.xy) * voxel_to_ndc; output[1].p.xy = (output[1].p.xy) * voxel_to_ndc; output[2].p.xy = (output[2].p.xy) * voxel_to_ndc; Without conservative rasterization: output[0].p.xy = (output[0].p.xy + normalize(delta_02 - delta_10)) * voxel_to_ndc; output[1].p.xy = (output[1].p.xy + normalize(delta_10 - delta_21)) * voxel_to_ndc; output[2].p.xy = (output[2].p.xy + normalize(delta_21 - delta_02)) * voxel_to_ndc; This should shift the voxel-space vertex coordinates outwards over one voxel. Though, if I scale this (by a factor 2 for example), the problems remain. So I wonder if this is still somehow related to conservative rasterization or not? It even gets more extreme, since complete planes disappear depending on the camera angles: bug.mp4 float g_voxel_size = 0.1f; // The size of a voxel in meters (view space) float g_voxel_inv_size = 10.0f; uint g_voxel_grid_resolution = 128u; // The resolution of the voxel grid float g_voxel_grid_inv_resolution = 0.0078125f;
  14. C++ Strange behavior with extern definition

    I do not have the c4droid app myself (I am not going to pay for a GCC compiler app, since GCC is a free compiler and CppDroid is a free app that essentially does the same thing ). But maybe this Q&A on StackOverflow can help you: https://stackoverflow.com/questions/11085235/g-c4droid-and-picking-up-includes (Try holding down the compile button and see if some option pops up asking to compile multiple source code files.) Though, if you just want to create small experiments and toy around with C++, and you have an internet connection, you can use an online compiler, such as Wandbox (https://wandbox.org/), which supports more than one source code file.
  15. C++ Strange behavior with extern definition

    You can alternatively consider using inline (or even constexpr if possible) variables in C++17. That way you can create for example header-only APIs with global variables. And more importantly do not forget to link. Undefined references are not compiler errors, but linker errors. (Though, if you forget to compile something, you can of course not link it.)
  • Advertisement