Full Screen/Post Processing PS On SDK CubeMap Example

Started by
13 comments, last by BryanCroteau 12 years, 5 months ago
I am working on a tech demo for my programming portfolio, and I am using the CubeMapGS Sample in the DirectX SDK Sample Browser. Like all computer graphics tutorials, it is less of a tutorial and more of a gratuitous high-level explanation of nothing useful to somebody without code that does what they want, (though I suppose the incompetence of humanity in coming up with decent tutorials for any topic --except how to build a Lego-- is a discussion for another time).

My tech demo has very specific needs.

Let's say I have a PS:


float4 PS_Final( VS_OUTPUT_SCENE vin ) : SV_Target
{
return float4(1.0, 1.0, 0.0, 1.0);
}

And with no guarantees on the syntax, this shader should return yellow pixels. Now, I want to apply this shader to the entire screen after everything else has been rendered. I have been told that you basically need to render a screen quad and apply the shader to that quad. Except I wasn't told HOW to do this, of course, because one thing you can count on on the internet, 0% of graphics code actually compiles and runs.

So I tried migrating some of the code from the "render a triangle" tutorial into the cubemap tutorial, and it didn't run. Some horrible thing that I didn't do quite right. Maybe it's the fact that it takes 300 lines of code to render one triangle, and I tried finding a way to migrate the important code into the cubemap sample which is itself 900 lines long without knowing anything at all about the DirectX library.

What I need is step by step instructions on how to apply this post processing pixel shader. Do I need information about computer graphics, history, theory, pretty mathematical representations? Not really. Will those things be helpful? Not at all. What do I need? Instructions that when followed lead directly to my goal, nothing more.

If you can't provide instructions that a 6-year old could follow, please don't bother trying to help. There is PLENTY of useless non-instruction information on the internet. You can't expect any human being to look at a picture on the box and put the pieces together without instructions.
Advertisement
I am not willing to dumb it down as far as you requested, because if that were necessary then you would have no place even attempting what you are attempting.
We can all assume one of the first things you learn how to do is to set a projection matrix and to create a vertex buffer and render those vertices to the screen.
Right?
If that is already above your abilities then you have some more tutorials to read, and yes these things are covered in tutorials. This is the bare necessity for getting anything onto the screen, which is why not every tutorial covers it. It must be assumed you already know it.

So let’s assume you do know that much, because I am not willing to cover it, nor is anyone else.
Draw a full-screen quad.

#1: Create an orthogonal projection matrix that spans the entire screen width and height. Study the D3DXMatrixOrthoLH() function. D3DXMatrixOrthoRH() may do just as well because you may as well just turn culling off for this process. -1.0f for near, 1.0f for far. Fairly sure you can figure out how to pass the window size to that function on your own. IDirect3DDevice9::SetTransform( D3DTS_PROJECTION, mat ) that matrix.
#2: No need for any camera matrix. Set the view matrix to identity.
#3: Create a few vertices at [0,0], [1,0], [0,1], and [1,1]. If you know how to make a vertex buffer, and you do, then this is no problem.
#4: Make a matrix that scales the X and Y up to the screen width and height. D3DXMatrixScaling( MAT, SCREENWIDTH, SCREENHEIGHT, 1.0f ) and then apply that to the world matrix. Now your vertices will be scaled to fit the screen.
#5: Put the source texture(s) into the slots in which they belong. Whatever image you are trying to render over the screen needs to be in slot 0. If you want to read from multiple targets, put them into multiple texture slots. The rest here has nothing to do with just “rendering a full-screen quad”. I am sure you can figure this out.


Sometimes the lack of completeness in tutorials is annoying, but when you have enough experience you are able to fill in the gaps, and that is what the authors expect. Because if every author for every tutorial had to explain things from the ground up we, as humanity, would not be progressing very fast. We would all be spending our time covering and re-covering the basics before we could present anything new.
It is generally understood when writing an advanced tutorial that your readers will have a firm understanding of the basics.
And don’t feel left-out. I used to get angry at tutorials that did not feed me every tidbit of information. It took many years to realize that that was just because I was trying to stand on the shoulders of giants to accomplish something without actually understanding what I was trying to do or what they had done.

In a few years you will look back on your former self and sigh. And then move on to finishing that crazy new graphics algorithm you are inventing.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid


I am not willing to dumb it down as far as you requested, because if that were necessary then you would have no place even attempting what you are attempting.
We can all assume one of the first things you learn how to do is to set a projection matrix and to create a vertex buffer and render those vertices to the screen.
Right?
If that is already above your abilities then you have some more tutorials to read, and yes these things are covered in tutorials. This is the bare necessity for getting anything onto the screen, which is why not every tutorial covers it. It must be assumed you already know it.

So let’s assume you do know that much, because I am not willing to cover it, nor is anyone else.
Draw a full-screen quad.


No, I don't know how to do any of that. I haven't done any graphics programming since college and even then it was in OpenGL and my teachers provided detailed, step by step instructions that you could slavishly follow and believe it or not, it worked remarkably well at the time. But what I am saying is, these things are NOT covered in any tutorials.

The code is given to you with a high-level explanation and that's it. It's like showing a person an airplane and then explaining the physics that make it fly. It doesn't matter if the learner understand the physics, they'll still crash.

When somebody makes a tutorial to DO something, they cannot assume the learner knows anything at all. You don't need to know the details or even the basics, you just need to DO something and over time the basics will become obvious.


#1: Create an orthogonal projection matrix that spans the entire screen width and height. Study the D3DXMatrixOrthoLH() function. D3DXMatrixOrthoRH() may do just as well because you may as well just turn culling off for this process. -1.0f for near, 1.0f for far. Fairly sure you can figure out how to pass the window size to that function on your own. IDirect3DDevice9::SetTransform( D3DTS_PROJECTION, mat ) that matrix.
#2: No need for any camera matrix. Set the view matrix to identity.
#3: Create a few vertices at [0,0], [1,0], [0,1], and [1,1]. If you know how to make a vertex buffer, and you do, then this is no problem.
#4: Make a matrix that scales the X and Y up to the screen width and height. D3DXMatrixScaling( MAT, SCREENWIDTH, SCREENHEIGHT, 1.0f ) and then apply that to the world matrix. Now your vertices will be scaled to fit the screen.
#5: Put the source texture(s) into the slots in which they belong. Whatever image you are trying to render over the screen needs to be in slot 0. If you want to read from multiple targets, put them into multiple texture slots. The rest here has nothing to do with just “rendering a full-screen quad”. I am sure you can figure this out.


1) Where? In the initialization, render, or re-size callbacks? How will this conflict with the existing code in the tutorial? How can I know?
2) Once again, where? There are 900 lines of code in the sample I am working with.
3) No, I don't know how to do this, because when I tried it crashed on startup and gave an error message: "the direct3D device has a non-zero reference count, meaning some objects were not released."
4) Again, where?
5) The resource I need is a cube map defined in the FX file already by the author of the tutorial. As far as I know it is in scope of any shaders I try to apply in various places. I applied my shader in place of all the shaders in the file already, with different results. For instance the reflection on the car's windows was the effect I wanted, but I have no way of applying that to the whole screen.


Sometimes the lack of completeness in tutorials is annoying, but when you have enough experience you are able to fill in the gaps, and that is what the authors expect. Because if every author for every tutorial had to explain things from the ground up we, as humanity, would not be progressing very fast. We would all be spending our time covering and re-covering the basics before we could present anything new.
It is generally understood when writing an advanced tutorial that your readers will have a firm understanding of the basics.
And don’t feel left-out. I used to get angry at tutorials that did not feed me every tidbit of information. It took many years to realize that that was just because I was trying to stand on the shoulders of giants to accomplish something without actually understanding what I was trying to do or what they had done.


We wouldn't progress fast if we had to explain the basics? I fully disagree, and I can provide an alternate theory that contradicts your statement with evidence and examples, and an entire book, to back it up.

You don't need to understand what the giants did or the fundamentals that the used to invent something new. You don't need any formal training to follow instructions and you don't need any knowledge to learn from mistakes as long as 1) You receive feedback on those mistakes and 2) there are no consequences to those mistakes that prevent you from advancing.

For instance, if you make a mistake flying an airplane you die. No feedback to let you get better, and an important consequence that prevents you from trying again, namely, the fact that you are dead.

I believe there is a quote from Dune: "Muad'Dib learned rapidly because his first training was in how to learn." When you go ice skating, the little Asian girls skate the best and fall down every few seconds. Humans learn by failing over and over and over in rapid succession with constant feedback. The book "The Talent Code," or even just the first chapter which is available for viewing online, has a number of examples.

Take the Shazzam shader editing tool for WPF/Silverlight. The environment is set up so that you have immediate feedback when you make a change, and you can immediately see the visual effect of the change. Furthermore, when you read through the tutorials provided inside the program (which by the way is a fantastic place to put them), there are commented lines that say: "change this line to this and see what happens" and: "do this and try getting it to look like this." If you think back about how YOU learned Direct3D, I guarantee you the sum of your experience has followed the same pattern, try something, if it doesn't work try something else, and over time you master the details and are ready to stand on your own without the shoulders of giants.


In a few years you will look back on your former self and sigh. And then move on to finishing that crazy new graphics algorithm you are inventing.


L. Spiro


Hopefully in a few years everyone will look back and see the former methodology of teaching Direct3D and laugh at how stupid it was.
I may be walking into a bee hive here, but I am going to try to help - and give some suggestions even if you don't want them. The basic topics that you have questions about are the very first principles of working in computer graphics and their APIs. In order to get something done, you must have some basic background knowledge of the subject or else it isn't going to do you any good to get through this tutorial task.

For example, do you have any concept of the rendering pipeline? There is geometry fed into the pipeline from vertex and index buffers when a draw call is executed, and that geometric data is transformed in a vertex shader to position it within the current view port. That transformation is done with world, view, and projection matrices, which are usually concatenated together and supplied to the vertex shader through a constant buffer. That transformed geometry is then rasterized to produce pixels, which are then subsequently processed with the pixel shader (similar to what you have already provided). This overview covers the minimal pipeline setup, with all other programmable stages disabled (which is done by setting null into the corresponding shader slots).

What you are trying to do is cover the entire viewport with a single triangle or two, so that with a minimal amount of geometry you are going to invoke a pixel shader for every pixel of your render target. The choice is yours in how to accomplish this - you create vertex buffers with some input geometry, and at the output of the vertex shader you need to have the x and y coordinates over the range of -1 to 1 being covered by the geometry. If you use one triangle, then you can just make the input vertex positions be large (such as v0= {-1,-1,0,1} v1={-1,20,0,1} v2={20,20,0,1}. With these vertex positions, your geometry doesn't need to be modified at all - you can simply pass the input values to the output of the vertex shader. This will then produce a single fragment for each of your pixels, which is what you wanted in the end.

The actual code snippets to create a vertex buffer, bind it to the pipeline, setup the corresponding pipeline states, and then call the draw call are all available on the internet. In fact, most of them are available in the DXSDK documentation... However, I would suggest that you not simply hunt for the code snippet that you need for this one task, and rather that you invest some time into understanding more of what you are doing with the pipeline. I think you instructors in college may have done you a dis-service by spoon feeding you code tasks - if you don't know anything at all about the underlying system that you are programming, then have you actually learned anything by following a recipe style list of things to do?

I don't think so - but that is just my opinion. So when you write your code sample for your portfolio, if someone checks it out and they ask you to modify it to do something else, what will you tell them??? I know it is a gigantic topic to dive into, but if you put the time into it, you will surely learn about it and be better off not to need to rely on others to provide sample code for tasks like this. Again, this is just my opinion, but I truly hope that you follow my advice and spend some time learning the background info on at least some of this stuff - you just might like working with it!

I may be walking into a bee hive here, but I am going to try to help - and give some suggestions even if you don't want them. The basic topics that you have questions about are the very first principles of working in computer graphics and their APIs. In order to get something done, you must have some basic background knowledge of the subject or else it isn't going to do you any good to get through this tutorial task.


I have rendered my own scenes in opengl, texture loading, terrain generation with perlin noise, and custom shaders. I fully understand the high level concepts, and I understand pixel shaders rather well. I don't work as an engine programmer, I'm actually a tools programmer, and recently I created an HSV color picker for WPF with the bulk of the work being done on the GPU by an HLSL shader. My area of concern as a programmer is human-computer interaction and ease of use, not rote memorization of particular implementations. If it's any consolation, I have read through every documentation page in the D3D SDK sample browser that deals with the basics. As I have said, they are not tutorials, I cannot think of an analogy better than the airplane analogy I gave above.


For example, do you have any concept of the rendering pipeline? There is geometry fed into the pipeline from vertex and index buffers when a draw call is executed, and that geometric data is transformed in a vertex shader to position it within the current view port. That transformation is done with world, view, and projection matrices, which are usually concatenated together and supplied to the vertex shader through a constant buffer. That transformed geometry is then rasterized to produce pixels, which are then subsequently processed with the pixel shader (similar to what you have already provided). This overview covers the minimal pipeline setup, with all other programmable stages disabled (which is done by setting null into the corresponding shader slots).


What you are trying to do is cover the entire viewport with a single triangle or two, so that with a minimal amount of geometry you are going to invoke a pixel shader for every pixel of your render target. The choice is yours in how to accomplish this - you create vertex buffers with some input geometry, and at the output of the vertex shader you need to have the x and y coordinates over the range of -1 to 1 being covered by the geometry. If you use one triangle, then you can just make the input vertex positions be large (such as v0= {-1,-1,0,1} v1={-1,20,0,1} v2={20,20,0,1}. With these vertex positions, your geometry doesn't need to be modified at all - you can simply pass the input values to the output of the vertex shader. This will then produce a single fragment for each of your pixels, which is what you wanted in the end.

The actual code snippets to create a vertex buffer, bind it to the pipeline, setup the corresponding pipeline states, and then call the draw call are all available on the internet. In fact, most of them are available in the DXSDK documentation... However, I would suggest that you not simply hunt for the code snippet that you need for this one task, and rather that you invest some time into understanding more of what you are doing with the pipeline.


Yes, that's all nice. And I promise that if I understood how to do this I wouldn't have made this thread.


I think you instructors in college may have done you a dis-service by spoon feeding you code tasks - if you don't know anything at all about the underlying system that you are programming, then have you actually learned anything by following a recipe style list of things to do?


What evidence do you have to back up this statement? Are you a teacher? What statistical information do you have correlating a particular technique with retention and self-reliance?


I don't think so - but that is just my opinion. So when you write your code sample for your portfolio, if someone checks it out and they ask you to modify it to do something else, what will you tell them??? I know it is a gigantic topic to dive into, but if you put the time into it, you will surely learn about it and be better off not to need to rely on others to provide sample code for tasks like this. Again, this is just my opinion, but I truly hope that you follow my advice and spend some time learning the background info on at least some of this stuff - you just might like working with it!


Oh I would love to. Here is the use case scenario that I encountered. Right, I search for tutorials on the internet on learning Direct3D, and every last one is exactly the same: mile-high overview of the topic with mathematical graphs and representations of vector spaces, along with working code. It is missing the most important ingredient, the very essence of learning, and that is interaction and feedback. I understand what you are saying, and you think I would be better off learning from the ground up, but what I am trying to tell you is, and this is not just true for Direct3D, the information out there is not good enough. I know for a fact that if I knew everything there was to know about Direct3D, I could write a tutorial that nobody would ever be confused about.

I work hard every day and even on weekends implementing the functionality my clients want for my company. WPF is a very counter-intuitive framework for computer science students because it goes against everything you learn from assembly up. All computer instructions translate into load, store, math, conditional, and jump statements in the end. Everything from delegates and polymorphism to threading and serialization and abstract data types are all just combinations of these five elements. But WPF throws a lot of the traditional programming styles out the window and uses instead static property tables and automatic synchronization of variables and whatnot. It was extremely difficult to learn and the tutorials out there are just as bad as Direct3D.

I am not saying that what you ask me to do is impossible, I am saying there is a better way. I promise you that if you researched it yourself and experimented with people who have never used graphics libraries before, you would quickly change your mind about spoon feeding tasks.
Don't use DirectX. Use the following:

1. Unity. Awesome for quick demos and support post processing shaders / real time cube maps.
2. Any other game engine that supports shaders. Lots of them
3. Immediate mode OpenGL (i.e. glVertex, glBegin, ...) and blend your draw results with a color (if you just need blending)

Curious why you chose to work with a close to the metal DirectX sample if you're just looking for quick results.
As someone who started graphics programming self-taught, using Direct3D documentation as a starting point; they're very well explained. Try starting with the tutorial section in the Src samples (Mine are located in C:\Program Files (x86)\Microsoft DirectX SDK (February 2010)\Samples\C++\Direct3D\Tutorials).

Drawing a fullscreen quad is a matter of drawing a quad with vertices at (-1, -1, 0 ) (-1, 1, 0 ) (1, 1, 0 ) (1, -1, 0 ) without applying any transformation (pass those vertices "as is" in the vertex shader, or use an identity matrix for the world, view, and projection matrices).
An identity matrix is a matrix filled mostly with 0s, but with 1 when column number = row number.

To understand the vertex processing stage, what you get pre-VS and post-VS; read all the topic in here. It's just math, but in plain english, everything the GPU render is in XY space from (-1, -1) to (1, 1); the math just makes x = 459.5 become x = 0.22 if the triangle is in the screen. If it's outside the screen, it's just beyond the [-1; 1] range and the GPU rasterizer discards it. This is explained here.
"world" transform moves, rotates and scales your object, "view" does the same but in the opposite direction to account the camera (if your camera moves right, it's the same as if the camere didn't move but everything is moving to the left), "projection" is just some cool math that makes stuff that is far away to become smaller. This picture shows all the way playing with the projection from perspective projection towards orthographic projection.

So, when you use indentity matrices as world, view, and projection, you're basically not doing anything to the set of vertices; they'll just be rendered untransformed. If your quad goes from (-1, -1) to (1, 1); voilá you get a fullscreen quad covering the entire screen.

When you're done with it, move on to how the lighting works.

Hope this helps
Cheers
Dark Sylinc

What evidence do you have to back up this statement? Are you a teacher? What statistical information do you have correlating a particular technique with retention and self-reliance?

I actually have done some teaching, as well as designing courses at a college level. While I don't have any statistical data to back up my claims, I do have some experience working with others on these topics. I've also done some teaching in the corporate environment on computer graphics topics too, and had similar feedback. Spoon feeding code doesn't work in my experience - for me or for my colleagues, or for any students that I have seen come through the classes. Retention and understanding are typically better if someone understands why they are making the API calls.

Do you have statistical data or teaching experience to refute my claims? If not, then I think it is just my opinion against yours...


I don't think so - but that is just my opinion. ...

As I mentioned, this is just my opinion. You are free to take the suggestions or leave them.


Oh I would love to. Here is the use case scenario that I encountered. Right, I search for tutorials on the internet on learning Direct3D, and every last one is exactly the same: mile-high overview of the topic with mathematical graphs and representations of vector spaces, along with working code. It is missing the most important ingredient, the very essence of learning, and that is interaction and feedback. I understand what you are saying, and you think I would be better off learning from the ground up, but what I am trying to tell you is, and this is not just true for Direct3D, the information out there is not good enough. I know for a fact that if I knew everything there was to know about Direct3D, I could write a tutorial that nobody would ever be confused about.

It sounds like you are looking for a program that does precisely what you are looking for - which will not happen. I can honestly feel for you that you are frustrated about what is out there, but I don't think there are other programming arenas out there that do the same thing... Again, maybe I am wrong - this is just my opinion.


I work hard every day and even on weekends implementing the functionality my clients want for my company. WPF is a very counter-intuitive framework for computer science students because it goes against everything you learn from assembly up. All computer instructions translate into load, store, math, conditional, and jump statements in the end. Everything from delegates and polymorphism to threading and serialization and abstract data types are all just combinations of these five elements. But WPF throws a lot of the traditional programming styles out the window and uses instead static property tables and automatic synchronization of variables and whatnot. It was extremely difficult to learn and the tutorials out there are just as bad as Direct3D.

I absolutely don't doubt that you work hard - in fact I am quite convinced of the opposite. I just think you are approaching the topic from the wrong direction. You know the high level stuff - so you just need to spend a day with the documentation or a book and work through the problem. There won't be any tutorial that does precisely what you are looking for... However, once you wrap up the work on that project, why not write a tutorial to show how it should be done???


I am not saying that what you ask me to do is impossible, I am saying there is a better way. I promise you that if you researched it yourself and experimented with people who have never used graphics libraries before, you would quickly change your mind about spoon feeding tasks.

That is a little bit disingenuous, since you have used graphics libraries already. If you have done similar research, I would love to see any information that you can share on the topic.

No, I don't know how to do any of that. I haven't done any graphics programming since college and even then it was in OpenGL and my teachers provided detailed, step by step instructions that you could slavishly follow and believe it or not, it worked remarkably well at the time. But what I am saying is, these things are NOT covered in any tutorials.

Starting with your first polygon.
Setting up DirectX 10
Rendering a primitive (means creating a vertex buffer, setting up projection matrices, and rendering them, as I said in my first post)
And more (lower posts are older and more basic)
Not to mention that the DirectX Sample Browser has full source and explanations for every step from creating a device to rendering a triangle to post processing. Sort by skill level.



When somebody makes a tutorial to DO something, they cannot assume the learner knows anything at all. You don't need to know the details or even the basics, you just need to DO something and over time the basics will become obvious.

We wouldn't progress fast if we had to explain the basics?

No, we wouldn’t progress as fast if we (the people who write tutorials) had to reiterate every bit of the knowledge that leads up to the material being presented. You can’t expect a tutorial on deferred rendering to explain how to set up a device.



You don't need to understand what the giants did or the fundamentals that the used to invent something new. You don't need any formal training to follow instructions and you don't need any knowledge to learn from mistakes as long as 1) You receive feedback on those mistakes and 2) there are no consequences to those mistakes that prevent you from advancing.
[…]
[color=#1C2837][size=2]…If you think back about how YOU learned Direct3D…


When I was a kid, I decided it would probably be a good idea not to learn things, but to learn to learn things.
I started C++ on my own when I was 14. My second or third program was made using Glide (yes I am that old). I drew pixels of various colors all over the screen, though I didn’t even understand what variable “scopes” meant.
I didn’t know of any forums or sites where I could ask for help. I scoured the Internet and used whatever tutorials I could find, and bought a book on C++.
And to be honest, learning both C++ and graphics programming was too daunting for a while, so I dropped graphics programming and just did C++ for a year before picking back up on graphics programming.

I guess my point is that:
#1: I didn’t try to do post-processing without first having learned to make a device and render a triangle.
#2: And there are enough resources out there for one to get the point of post-processing, step-by-step, without ever having to ask questions online (IE: relying entirely on tutorials).


It really is all about learning how to learn.
Your situation now is like when I was trying to learn both C++ and Glide at the same time. You need to start with a foundation and move up step-by-step.
The DirectX Sample Browser has samples suitable for you. There are also basic-level tutorials and books you can buy.

The problem is not that the tutorials are lacking, it’s that you haven’t structured the way you approach this particular goal.
I’m sure you are working hard. Now it is time to also work smart.
Inevitably, you will need to build a foundation that allows you to create a device and render some triangles.
So why don’t you do that first and then come back if you have more questions later?


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

[color="#284b72"]bdcroteau,



This is a little off topic but as you already have taken the thread that way I figured what the hell.

I can say without a doubt it is a pity reading posts like yours Mr. Bdcroteau, well rather the responses. You have several brilliant and kind users who are attempting to help you and all you do is give them hell for not giving you the exact details of what you want (basically code to copy). On that same note, unlike the others I HIGHLY doubt you work hard at your job. By the tone of your posts you most likely go around other forums demanding help and then get snotty when it's not a copy/paste of code that you want (this is clearly stated in your first post).


:rolleyes: :rolleyes: :rolleyes: :rolleyes:


As for there are no "helpful sites" out there you again obviously haven't worked very hard in searching. A simple "dx11 engine tutorial" gives several links including : http://www.directxtutorial.com/ which gives ... gasp .. step by steps instructions *that work* Same with http://www.rastertek.com/tutindex.html . Found both these sites in 30 seconds of my time. You're a computer programmer and don't know how to do a search? :blink:


I don't have any other words for you but Jason Z, YogurtEmperor and others , don't let new users like this detour your [continious] help on these forums.

This topic is closed to new replies.

Advertisement