Advertisement Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

Community Reputation

652 Good

About SHilbert

  • Rank

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. SHilbert

    Multi pass texturing

    Looks like maybe it's because you're calling SetTexture inside Begin/EndPass. If the application changes any effect state using any of the Effect::Setx methods inside of a ID3DXEffect::BeginPass/ID3DXEffect::EndPass matching pair, the application must call ID3DXEffect::CommitChanges to set the update the device with the state changes. If no state changes occur within a ID3DXEffect::BeginPass and ID3DXEffect::EndPass matching pair, it is not necessary to call ID3DXEffect::CommitChanges. [/quote] So one option is to call mFX->CommitChanges(). I don't think you actually need to manually change the texture per pass at all, though. If you just define 3 texture uniforms, instead of the single gTex you have now, and just fill them in with your 3 different textures before you begin drawing, and sample from the right one in each VS, the effect system will sort it all out for you. EDIT: FYI, to further clean up your effect rendering loop, you can specify the blend modes in your FX file too, by setting states inside the passes: technique TerrainMultiTexTech { pass P0 { // Specify the vertex and pixel shader associated with this pass. vertexShader = compile vs_2_0 TerrainMultiTexVS(); pixelShader = compile ps_2_0 TerrainMultiTexPS0(); AlphaBlendEnable = FALSE; } pass P1 { // Specify the vertex and pixel shader associated with this pass. vertexShader = compile vs_2_0 TerrainMultiTexVS(); pixelShader = compile ps_2_0 TerrainMultiTexPS1(); AlphaBlendEnable = TRUE; SrcBlend = SRCALPHA; DestBlend = INVSRCALPHA; } pass P2 { // Specify the vertex and pixel shader associated with this pass. vertexShader = compile vs_2_0 TerrainMultiTexVS(); pixelShader = compile ps_2_0 TerrainMultiTexPS2(); AlphaBlendEnable = TRUE; SrcBlend = SRCALPHA; DestBlend = INVSRCALPHA; } }
  2. SHilbert

    [Dx8] Texture & Blending

    I didn't even notice that it was DESTBLEND in your post and not SRCBLEND until you pointed it out. Easy mistake to make. No problem. A third of that code is just from a quick start tutorial somewhere on the internet anyway, to make the window & device & such. When you do something like D3DTA_TEXTURE | D3DTA_ALPHAREPLICATE, it means it takes the (r,g,b,a) from the texture (the D3DTA_TEXTURE part) and turns it into (a,a,a) (the D3DTA_ALPHAREPLICATE part.) So when you do this: [source lang="cpp"] g_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); g_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); g_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE|D3DTA_ALPHAREPLICATE); [/source] It means: colorarg1 = (r,g,b) from the texture colorarg2 = sample the alpha from the texture and produce a triplet (a,a,a) modulate = the output is colorarg1 * colorarg2 = (r,g,b) * (a,a,a) = (r*a, g*a, b*a) So if the texture at that point is (r,g,b,a) then the overall of that stage is (r*a, g*a, b*a, a). (The alpha processing is just left as default.)
  3. SHilbert

    Multi pass texturing

    Looks like you have alpha blending turned on for each pass, but the alpha value your pixel shaders are outputting is diffuse.a, which is probably just 1. So each pass is drawing opaquely over the previous one. I'm not sure why you're not doing this all in one pass in a single pixel shader, though -- it doesn't seem like you'd run out of instruction slots or textures? I might be wrong though. If you do want to do multipass, you probably want to draw the first pass w/ alpha blending turned off, without even referring to the blend map. Then, for the subsequent passes, turn on alpha blending, and instead of multiplying the tiled texture's color by the green or blue channel from the blend map, you use the green or blue channel as the alpha component you return from the pixel shader. Not sure why your texture order is swapped (i.e. why stone is mapped to blue instead of green) though.
  4. SHilbert

    [Dx8] Texture & Blending

    I figured this may be more easily expressed in code so I put it together using DX9 and C++ (I haven't got VB6 or a DX8 SDK, sorry.) But the code should still be easy enough to read since it's mostly the Direct3D parts that matter. Here it is: This is the interesting part: [source lang="cpp"]void Draw() { g_device->BeginScene(); // Common states we always use g_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); g_device->SetRenderState(D3DRS_LIGHTING, FALSE); g_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); // Render to 512x512 texture g_device->SetRenderTarget(0, g_rttSurf); D3DXMATRIX proj512x512; D3DXMatrixOrthoOffCenterRH(&proj512x512, 0, 512, 512, 0, -10, 10); g_device->SetTransform(D3DTS_PROJECTION, &proj512x512); // Clear all components to zero g_device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); // Premultiply alpha in the source texture using texture stage g_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); g_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); g_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE|D3DTA_ALPHAREPLICATE); // Set blend mode to (ONE, INVSRCALPHA) g_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); g_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); // Draw textures 1 & 2 DrawTexturedQuad(g_tex1, 0, 0, 512, 512); DrawTexturedQuad(g_tex2, 0, 0, 512, 512); // Now switch to the main render target (1024x512) g_device->SetRenderTarget(0, g_defaultRT); D3DXMATRIX proj1024x512; D3DXMatrixOrthoOffCenterRH(&proj1024x512, 0, 1024, 512, 0, -10, 10); // Clear to some random color g_device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255), 0, 0); // Reset texture stage settings to default g_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); g_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); g_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT); g_device->SetTransform(D3DTS_PROJECTION, &proj1024x512); // Left side. (render to texture side) // Draw the back texture, 0.png -- use normal alpha blending // (doesn't matter since it's opaque) g_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); g_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); DrawTexturedQuad(g_tex0, 0, 0, 512, 512); // Draw the offscreen texture we have generated. // It uses premultiplied alpha so we have to blend appropriately g_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); g_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); DrawTexturedQuad(g_rtt, 0, 0, 512, 512); // Right side. (control side) // Now go back and draw each texture on top of one another w/ default alpha blending. g_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); g_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); DrawTexturedQuad(g_tex0, 512, 0, 512, 512); DrawTexturedQuad(g_tex1, 512, 0, 512, 512); DrawTexturedQuad(g_tex2, 512, 0, 512, 512); // Done with scene, swap buffers, etc. g_device->EndScene(); g_device->Present(NULL, NULL, NULL, NULL); }[/source] I'm drawing to the offscreen render target every frame, but it's the same idea as what you have. Also I did it with a single texture stage, because there is no reason to multiply in vertex color for this example. Basically when drawing to the offscreen render target: (1) clear to black w/ zero alpha (2) set up texture stage 0 to multiply color components by alpha (3) draw your textures w/ src=one, dest=invsrcalpha Then when drawing to the target: (1) reset all texture stages to default (2) draw your checkerboard backdrop w/ an alpha blend (src=srcalpha, dest=invsrcalpha) or no blending at all (3) draw the render target texture using src=one, dest=invsrcalpha I hope that helps. Here's a screenshot of what it looks like:
  5. SHilbert

    [Dx8] Texture & Blending

    No worries! Hmm, it looks like it is a lot closer! It's like somehow it's rendering as if the alpha is squared (i.e., always less than it ought to be unless alpha = 1.) It's almost as if the alpha is getting premultiplied by itself along with the color parts. Could you maybe post the source as it is now? I'd like to take a look at all of the render states together.
  6. SHilbert

    Slow parallel code

    CLR Profiler is good and free. I seem to remember there being some trick to making it work with XNA but I don't recall what it was at the moment. It will tell you what you're allocating, how much, where and when. You can use the the performance counters exposed by .NET to view what the GC is doing. Basically you go start->run "perfmon.exe" and add counters from under ".NET CLR Memory" to your graph. You can set it up to only show GC info for your specific program too. http://msdn.microsof...y/x2tyfybc.aspx Also, one trick I have used is to just make a single object that is only referenced via a WeakReference, and every frame check if that WeakReference's Target is now null. In my game I plot these events on a scrolling graph and their frequency tells me how often gen0 collections are happening, which tells me how much garbage I am generating per frame. But that method requires more game-specific setup than the CLR Profiler/Performance Counter route.
  7. SHilbert

    [Dx8] Texture & Blending

    The same texture in 2 stages. The goal is to multiply the texture's normal RGB values by the texture's A value before it even gets to the blending stage. This makes the your texture effectively have "premultiplied alpha" at runtime, so you don't have to do it at or before load time. This isn't a pre-pass step, it's something you do every render. It's been ages since I worked with texture stages but I am pretty sure this sort of approach will work. If you don't care about vertex colors you can also do it in one stage like this, I think: (Stage 0) Texture = (your source texture) [background=rgb(250, 251, 252)]D3DTSS_COLOROP = D3DTOP_MODULATE[/background] [color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][background=rgb(250, 251, 252)]D3DTSS_COLORARG1 = D3DTA_TEXTURE[/background][/font] [color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][background=rgb(250, 251, 252)]D3DTSS_COLORARG2 = D3DTA_TEXTURE | D3DTA_ALPHAREPLICATE[/background][/font]
  8. SHilbert

    Order or 2D drawable entities

    Assuming you are working in C# since you mentioned avoiding LINQ. My first try would be this: Collect all the entities that are onscreen into a List, and use List.Sort with a custom Comparison<T> method. Don't use bubble sort! If you Clear() and re-used the visible entity list instance every frame, you will not generate any unnecessary garbage this way. I wouldn't try to do any schemes to sort only while entities move unless you can't get good enough performance this way, just because it is far simpler code to just sort right before rendering. In my experience you can sort a lot of objects this way and it will still be fast.
  9. If your worst case is literally finding the closest of a list of 10 objects once per frame, you could do anything and it would be fast. On the other hand, if you can rule out raycasts before even doing them, that is definitely worth doing. Like, if you know that your closest object had a distance of 6 meters, and you get to an object where the distance from the camera to the surface of its bounding sphere is 7 meters, you don't have to do any ray casts vs. its geometry at all, you can just throw it out.
  10. SHilbert

    Slow parallel code

    You mentioned that the code chunk you posted takes 48% of the time in one test. Do you know for sure that it is the part that is growing out of proportion to the other part as x increases? Like, as you increase x does that percentage go up, or down, or stay the same? I would time the first parallel loop, the second parallel loop, and your actual rendering code, all separately, and see which one is growing faster than the others as you increase x. You don't even need SlimTune, just use a System.Diagnostics.Stopwatch and draw the times, or percentages of frametime, on the screen. That way you can at least verify that you are targeting exactly the right section. Also, if you are not doing it already, I would make sure you compare tests with the same percentage of objects visible -- either all, or none, or some constant value like 50%. If you compare 60% objects visible at x=27 to 40% objects visible at x=28 you will see changes in the relative timing of different sections that are only based on that percentage, not on x. Also consider memory allocation and garbage collection. As you start allocating bigger chunks of RAM it starts getting more and more expensive, and the GC may start to thrash more and more often. One VERY SUSPICIOUS fact is that an allocation of 27^3 32-bit references is on the order of the size things start getting put in a separate large object heap (85,000 bytes.) I wrote a program to time how long it took per allocation averaged over 100,000 allocations, and I get this chart: (EDIT: The graph is actually milliseconds for a pair of allocations -- first allocating an array of that size, and then calling ToList on it.) Notice that the Y axis is milliseconds, though -- so if it is affecting you it is probably because the number of objects in your heap is much larger than my test program's, or you allocate many times per frame. Maybe try and see how frequently GCs are happening. There are some performance counters that can tell you lots of details about this. GCs can strike anywhere in your main loop even if they're caused by allocations in a localized position so it would be useful to rule that out first.
  11. SHilbert

    [Dx8] Texture & Blending

    You should be able to accomplish it with with texture stage states. For example, I think if you do add second color stage with D3DTSS_COLOROP = D3DTOP_MODULATE D3DTSS_COLORARG1 = D3DTA_CURRENT D3DTSS_COLORARG2 = D3DTA_TEXTURE | D3DTA_ALPHAREPLICATE can get the same effect. You only need to use this extra stage when rendering from non-premultiplied alpha textures, like your textures from 1.png and 2.png. You can also do the premultiplication 'offline' by modifying your texture files before you load them, or lock the texture after loading and do the premultiplication then. Or you could switch to DX9, which is close to 10 years old at this point and enjoys near universal support. Don't know if that is feasible in VB6 though, I don't know much about that ecosystem. This guy seems to have a library for using DX9 in VB (see post #14.)
  12. Geez, that is some poorly worded documentation. I think what it is saying is that if you pass NULL, then you get the situation described in the description column. As for the second column, I think the & !( ... ) is a horribly poor way of saying "bitwise anded with the bitwise inverse of ...." -- kind of weird they used ! instead of ~. That explains why "Vertices are ordered in a counterclockwise direction around each triangle." is next to "& !( D3DXTANGENT_WIND_CW )" -- D3DXTANGENT_WIND_CW is not set, so the ordering must be counterclockwise. So basically none of the flags mentioned in that column are set by default. All of the flags have a nonzero value, so if you pass NULL for the flags value you will of course have provided none of the flags. I don't think you want to specify all the flags since some of them are mutually exclusive, but I don't know what to recommend specifically. It does sound like you want to avoid passing D3DXTANGENT_CALCULATE_NORMALS though.
  13. SHilbert

    Issues with Occlusion Queries

    Are only the occlusion test models cubes or are the actual models cubes as well? Speed wise, occlusion queries only really make sense if the cost of doing the query is a lot less than the cost of just drawing the thing(s) it represents in the first place. For example, doing an occlusion query where you draw a simple bounding box (very cheap) in order to check if you need to draw an entire city block (very expensive if the geometry is complicated) is probably a good trade-off. Doing an occlusion query where you draw a single cube in order to avoid drawing another single cube, all of the above repeated up to 15,000 times, is probably not going to be effective. Even if you have more complicated models the sheer overhead of executing thousands of occlusion queries could make the speed suffer. If you are trying for speed when looking at the entire scene, I would first say to look into an instancing strategy to achieve better batching. 15,000 draw calls is going to be inherently slow even if you are drawing simple things. Getting occlusion queries right is tricky. If you still want to do the occlusion queries, it would probably be more worthwhile to do 1 occlusion query for a group of many nearby models, by drawing the group's bounding box -- that way even if the cost of drawing a model is the same as the cost of a query you can potentially spend 1 draw to save 100 draws. Some other miscellaneous thoughts: Is there more to your drawing code? It looks like you draw your models inside the occlusion query Begin/End, which doesn't make much sense to me. You don't want to be making occlusion queries unless you know the object in question is within your view frustum, otherwise the query is doomed from the start. I'm confused why you are drawing a wireframe for your occlusion test object. You should probably be drawing a solid bounding volume or else you are going to get some cases where the occlusion query reports zero pixels when there really might be some. I can see why you would draw the final objects as wireframes though, just to see if the occlusion tests are actually working. Might be worth reading what Shawn Hargreaves says in this thread on the XNA forums: http://forums.create...6244/33016.aspx
  14. SHilbert

    pixel shader input SV_Position

    EDIT: MJP's post below made me realize I should emphasize an important point: [font=courier new,courier,monospace]SV_Position[/font] is a semantic tag that means different things at different points. As an output from your vertex shader it is a set of homogenous coordinates. As MJP says below, as the input to the vertex shader it is in screen coordinates! As for the "transform", you get to do any extra transformation you want in your vertex shader! In the case of the shader you posted, there is no transformation at all, you are just returning the [font=courier new,courier,monospace]Pos [/font]value the same as you received it. So they will be identical. And then the screen space transformation MJP describes occurs before it gets to your pixel shader. I alrewady know that if float4 Pos is (-1,1,0,1) that will mean top-left of screen, (1,1,0,1) that will be top-right of screen...etc so i wanna know how it is transformed and what the values will mean. [/quote] So, the position at this point is in homogenous coordinates which means that for a given (x,y,z,w), the final value w implicitly divides all the others to obtain the final normalized device coordinates. The division operation is helpful for perspective projection since it involve a divide that you can't accomplish just with normal matrix algebra. So, the homogenous coordinates (-1,1,0,1) really mean (-1,1,0), and (1,0,1,5) really means (0.2,0,0.2). In D3D the normalized device coordinates (x,y,z) form a 3D cube like so: x: -1 (left of screen) to 1 (right) y: -1 (bottom of screen) to 1 (top) z: 0 (near) to 1 (far) The z-value is used for depth buffering. You will also hear of the homogenous coordinates or normalized device coordinates described as being in "clip space" or as "clip space coordinates," since that is the space in which triangle clipping is performed.
  15. SHilbert

    [Dx8] Texture & Blending

    So if I am interpreting you correctly, the problem is that doing this sequence: device.RenderTarget = DeviceBuffer Draw texture 0 w/ SRCBLEND=SRCALPHA, DESTBLEND=INVSRCALPHA device.RenderTarget = (an offscreen texture, which starts at transparent black, all values = 0x00000000) Draw texture 1 w/ SRCBLEND=SRCALPHA, DESTBLEND=INVSRCALPHA Draw texture 2 w/ SRCBLEND=SRCALPHA, DESTBLEND=INVSRCALPHA device.RenderTarget = DeviceBuffer Draw offscreen texture w/ SRCBLEND=SRCALPHA, DESTBLEND=INVSRCALPHA [/quote] is not equivalent to this sequence: device.RenderTarget = DeviceBuffer Draw texture 0 w/ SRCBLEND=SRCALPHA, DESTBLEND=INVSRCALPHA Draw texture 1 w/ SRCBLEND=SRCALPHA, DESTBLEND=INVSRCALPHA Draw texture 2 w/ SRCBLEND=SRCALPHA, DESTBLEND=INVSRCALPHA [/quote] And that makes sense, because they aren't equivalent! If you want to composite two transparent textures into one transparent texture, you are better off working all in pre-multiplied alpha -- both with the loaded textures and the offscreen destination texture. That is, modify your source textures so the R, G, B values are already pre-multiplied by the A values, and draw everything using D3DRS_SRCBLEND=D3DBLEND_ONE and D3DRS_DESTBLEND=D3DBLEND_INVSRCALPHA. If you don't work in pre-multiplied alpha the equation is harder to capture with simple blend operators. You may be able to avoid pre-multiplying the alpha on your source textures by rendering them with separate blending functions for the color channels & the alpha channel -- use these settings: D3DRS_SRCBLEND=D3DBLEND_SRCALPHA D3DRS_DESTBLEND=D3DBLEND_INVSRCALPHA, D3DRS_SEPARATEALPHABLENDENABLE = TRUE D3DRS_SRCBLENDALPHA=D3DBLEND_ONE D3DRS_DESTBLENDALPHA=D3DBLEND_INVSRCALPHA. [/quote] When drawing the offscreen texture to the final device buffer you must disable the separate alpha blending & just use D3DRS_SRCBLEND=D3DBLEND_ONE, D3DRS_DESTBLEND=D3DBLEND_INVSRCALPHA. I'm not sure if D3D8 supports this feature though -- I only have the D3D9 docs handy.
  • Advertisement

Important Information

By using, you agree to our community Guidelines, Terms of Use, and Privacy Policy. is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!