• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.


  • Content count

  • Joined

  • Last visited

Community Reputation

652 Good

About SHilbert

  • Rank
  1. Looks like maybe it's because you're calling SetTexture inside Begin/EndPass. [quote] If the application changes any effect state using any of the [u]Effect::Setx[/u] methods inside of a [b]ID3DXEffect::BeginPass[/b]/[b]ID3DXEffect::EndPass[/b] matching pair, the application must call [u]ID3DXEffect::CommitChanges[/u] to set the update the device with the state changes. If no state changes occur within a [b]ID3DXEffect::BeginPass[/b] and [b]ID3DXEffect::EndPass[/b] matching pair, it is not necessary to call [b]ID3DXEffect::CommitChanges[/b]. [/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. [b]EDIT:[/b] 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: [CODE] 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; } } [/CODE]
  2. [quote name='testt' timestamp='1340969502' post='4953922'] I don't understand why I used D3DRS_DESTBLEND=D3DBLEND_ONE to rendering the texture and I don't tried D3DRS_SRCBLEND=D3DBLEND_ONE.. It's so obvious now that I look stupid [/quote] I didn't even notice that it was [b]DEST[/b]BLEND in your post and not [b]SRC[/b]BLEND until you pointed it out. Easy mistake to make. [quote name='testt' timestamp='1340969502' post='4953922'] If that doesn't bother you I keep your code in C++, I think this is a good example for me when I will turn to this language. [/quote] 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. [quote name='testt' timestamp='1340969502' post='4953922'] However, I have a last question because it's the only thing I didn't quite understand. The D3DTA_ALPHAREPLICATE doesn't allow to use vertex color because he take the informations only in the texture ? [/quote] 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. 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. 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: [url="http://shilbert.com/files/BlendTest.zip"]http://shilbert.com/...s/BlendTest.zip[/url] 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: [url="http://shilbert.com/pics/blendtest.png"]http://shilbert.com/pics/blendtest.png[/url]
  5. [quote name='testt' timestamp='1340748026' post='4953154'] Hi and sorry for my absence (I had some problems with my pc). [/quote] No worries! [quote name='testt' timestamp='1340748026' post='4953154'] Edit : The problem with blending of two colors has been resolved, there remains the problem of alpha too low.. See [url="http://hpics.li/130ab20"]here[/url]. [/quote] 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. [quote name='Narf the Mouse' timestamp='1340734312' post='4953086'] I'll check if it's the garbage collector - Does anyone know of a free/cheap memory profiler? Manually checking probably wouldn't be quite as easy. [/quote] [url="http://www.microsoft.com/en-us/download/details.aspx?id=16273"]CLR Profiler[/url] 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. [url="http://msdn.microsoft.com/en-us/library/x2tyfybc.aspx"]http://msdn.microsof...y/x2tyfybc.aspx[/url] [url="http://blogs.msdn.com/b/maoni/archive/2004/06/03/148029.aspx"]http://blogs.msdn.co.../03/148029.aspx[/url] 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. [quote name='testt' timestamp='1340563808' post='4952391'] Yes, I know it's possible, but I don't understand exactly how Shilbert told me to do that. Use the same texture in 2 stages to separate opaque pixel and transparent pixel (with a different blending operation for each) or 2 textures in 2 stages for blending between them ? [/quote] 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) [left][background=rgb(250, 251, 252)]D3DTSS_COLOROP = D3DTOP_MODULATE[/background][/left] [left][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3][background=rgb(250, 251, 252)]D3DTSS_COLORARG1 = D3DTA_TEXTURE[/background][/size][/font][/color][/left] [left][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3][background=rgb(250, 251, 252)]D3DTSS_COLORARG2 = D3DTA_TEXTURE | D3DTA_ALPHAREPLICATE[/background][/size][/font][/color][/left]
  8. 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. [quote name='MARS_999' timestamp='1340418789' post='4951899'] Well so far from what I can determine, the std::multimap is faster when I start adding lots of objects. If one a few about the same. Say player clicks on object and camera is at an angle where their could be 10 objects in a line one behind each other when doing the ray test, this shouldn't happen very often but seeing what I see so far, I am switching to the multimap version. [/quote] 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. [quote name='Narf the Mouse' timestamp='1340411728' post='4951874'] At the moment, I'm not working on instancing, and I'd really like to know why the parallel code experiences a sudden drop in speed. [/quote] 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 [i]x[/i] increases? Like, as you increase [i]x[/i] 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 [i]x[/i]. 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 [i]x[/i]. 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 [b]VERY SUSPICIOUS[/b] 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: [img]https://dl.dropbox.com/u/514853/permanent/allocscale2.png[/img] [i](EDIT: The graph is actually milliseconds for a pair of allocations -- first allocating an array of that size, and then calling ToList on it.)[/i] 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. [url="http://msdn.microsoft.com/en-us/library/x2tyfybc.aspx"]There are some performance counters[/url] 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. 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 ...you 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. [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img] Don't know if that is feasible in VB6 though, I don't know much about that ecosystem. [url="http://www.vbforums.com/showthread.php?t=605201"]This guy[/url] seems to have a library for using DX9 in VB (see post #14.)
  12. Geez, that is some poorly worded documentation. I [i]think[/i] 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 [i]not[/i] set, so the ordering must be counterclockwise. So basically [i]none [/i]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. 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 [i]many [/i]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:[list] [*]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: [url="http://forums.create.msdn.com/forums/p/6244/33016.aspx"]http://forums.create...6244/33016.aspx[/url] [/list]
  14. [quote name='lomateron' timestamp='1340422743' post='4951912'] I want to understand very well how POSITION is tranformed to SV_POSITION [/quote] [b]EDIT:[/b] 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 [i]different things at different points[/i]. 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. [quote] 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 [i]homogenous coordinates[/i] which means that for a given ([i]x,y,z,w[/i]), the final value [i]w[/i] implicitly divides all the others to obtain the final [i]normalized device coordinates[/i]. 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 ([i]x,y,z[/i]) 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. So if I am interpreting you correctly, the problem is that doing this sequence: [quote] 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: [quote] 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 [i]source textures[/i] by rendering them with separate blending functions for the color channels & the alpha channel -- use these settings: [quote] D3DRS_SRCBLEND=D3DBLEND_SRCALPHA D3DRS_DESTBLEND=D3DBLEND_INVSRCALPHA, D3DRS_SEPARATEALPHABLENDENABLE = TRUE D3DRS_SRCBLENDALPHA=D3DBLEND_ONE D3DRS_DESTBLENDALPHA=D3DBLEND_INVSRCALPHA. [/quote] When drawing the [i]offscreen texture to the final device [/i]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.