Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

Everything posted by mossmoss

  1. My current task is to get some basic shaders written for our engine. This is the first time I've been working on shaders; I have a general understanding of how they work, setup, etc... but I've been hitting some specific problems. Basic setup: DX9 engine, using HLSL (but not Effects), compiling primarily for vs_2_0 and ps_2_0, though may use that and 3.0 going ahead. My current problem is that of per-pixel lighting and normal interpolation. (May be changed in the future for normal maps, but need to get the basics done first.) Here is the code: float4x4 g_Model; float4x4 g_ModelViewProj; struct VS_INPUT { float4 localPos : POSITION; float3 localNorm : NORMAL; float2 uv : TEXCOORD0; float4 diffuse : COLOR0; }; struct VS_OUTPUT { float4 projPos : POSITION; float4 diffuse : COLOR0; float2 uv : TEXCOORD0; float3 worldNorm : TEXCOORD1; }; VS_OUTPUT vshader(VS_INPUT I) { VS_OUTPUT O; O.projPos = mul(I.localPos, g_ModelViewProj); O.worldNorm = mul(I.localNorm, (float3x3) g_Model); O.diffuse = I.diffuse; O.uv = I.uv; return O; } float4 pshader(VS_OUTPUT I): COLOR { // just a sample light direction (towards light) for testing float3 light = normalize(float3(1.0, -0.2, 0.5)); return I.diffuse * saturate(dot(light, normalize(I.worldNorm))); } This is dead-simple per-pixel lighting. But it doesn't work, unless I change VS_OUTPUT to this: struct VS_OUTPUT { float4 projPos : POSITION; float4 diffuse : COLOR0; float2 uv : TEXCOORD1; float3 worldNorm : TEXCOORD0; }; The only difference is that I swapped the texcoord indices for uv and worldNorm. Then my per-pixel lighting and normals look fine. Likewise, I had some basic code working to sample a texture with the uv. That stopped working when I output the uv's to TEXCOORD1 instead of TEXCOORD0. So offhand, this doesn't seem like a shader issue, but more of a render/texture/sampler state issue. But I have no idea at this point what state is preventing TEXCOORD1 (or higher?) from being useful. Please, any hints, suggestions? Thanks...
  2. mossmoss

    normal x tangent = binormal?

    Quote:Original post by cignox1 I don't know if this could be the reason, but what does 3dstudio max when you mirror the geomtry? Does it mirror the tangent as well? Because if this is the case, then the bitangent will point the wrong direction. I remember there was a discussion here on gamedev some time ago about mirrored geometry, but it could heve been about uv mapping as well, I'm not sure... EDIT: check out these two topics: http://www.gamedev.net/community/forums/topic.asp?topic_id=340745 http://www.gamedev.net/community/forums/topic.asp?topic_id=352834&forum_id=12&gforum_id=0 They may be usefull... The mirrored geometry would almost certainly be the problem. The solution I've used is to include a bias term of either +1 or -1. (Can conviently fit into the w component of the shader register containing the xyz of your normal.) So bitangent = bias * (normal x tangent).
  3. Quote:My first version was a direct port from Perlin's original C source to Python. Perlin's first version, if I recall correctly, had second-order discontinuities, which would result in what you are seeing. He later improved his noise to remove that problem. EDIT: Here it is: http://mrl.nyu.edu/~perlin/paper445.pdf
  4. mossmoss

    Fast string look up

    Try a hashtable or hashmap. It's not part of the current standard, but some STL vendors have included an implementation as an extension. I would guess boost might have something along those lines as well. EDIT: 5 milliseconds is a *long* time for a simple lookup. Have you actually tried the STL map? You are assuming it's slow, but have you timed it?
  5. Quote:Original post by Drakkcon Okay, so I won't use std::list<Whatever&> but what about a class having a private reference to the dispatcher that it uses to raise events? Sure, that sounds normal. Quote: Also: It definitely compiles and I'm using Visual C++ 8 MSVC is not a paragon of compiler technology. That it compiles doesn't make it a good idea.
  6. I'd actually be surprised if it compiled... A good STL implementation would prevent you from making such a mistake.
  7. Offhand, that sounds like a **very, very bad idea**. STL containers work via copy mechanics, which is fine for pointers and objects (with decent copy constructors). References, however, do not. When the container attempts to perform certain operations on the "values" in the container, and do a copy, you are going to get very unexpected behaviour... your will begin losing some data and duplicating other data. Go with raw pointers and assert on NULL pointers, if there should not be any.
  8. mossmoss

    [C++] Memory leakage

    Quote: Since it is supplied to the constructor, I don't need to delete anything in the destructor right? Generally, it's a good practice that the section of code that allocates memory is also the one to free that memory. Which would jive with what you said. Just make sure that whoever is allocating the SSettings object (assuming it is allocated on the heap) also frees it. Quote: But do I have to set settings to NULL? Often, yes, you want to set it to NULL so you don't accidentally attempt to use the object later. But since this is a destructor, it's not necessary since the CMainScreen object itself will no longer exist. Quote: lso, is it only when I have used the new keyword that I need to use delete? Yes... new -> delete new[] -> delete[] malloc -> free
  9. mossmoss

    Some questions on precision

    Yes, as the magnitude of your floating-point numbers increase, the precision decreases. I am not sure what engine you were looking at... It may be using only floats because it is not intended for large-scale where the precision loss would matter. Or the engine authors, if they intended for such a large-scale, didn't understand this issue. In any case, here are a couple suggestions. First, keep this document handy, something everyone coding should know: http://www.physics.ohio-state.edu/~dws/grouplinks/floating_point_math.pdf Second, determine if the loss of precision is at all important. What are your numbers going to represent? What units? (Inches, meters, miles...?) What is the set of values you need to represent? (For example, you might say, "My world needs to be 100 kilometers wide and I need per-meter precision.") Third, once you break it down to what a delta of 1.0 means (and 0.1, 0.001, etc)... you should be able to determine whether you can keep your precisions at the outskirts. If you can, or can live with the error, might as well just use floats. However, if your precision requirements are such that floating-point alone is going to lose more precision than you'd like, you have a couple of options... Go all fixed-point, use 32- or 64-bits. Get a good fixed-point library or write your own (not all operations trivial, though). Do some combination of fixed-point and floating-point. Use fixed-point for the gross (ie. large), more global portion and use floating-point for the finer (ie. smaller), more localized portion.
  10. mossmoss

    "Recursive Dependencies" - How to do?

    For each file, figure out if you really need to #include another file. Let's take H1 as an example, #including H2. Why? What does it need out of H2? Here's a simple example: /* H1.h */ #include "H2.h" // declares Bar class Foo { public: void Run(Bar* bar); }; /* H2.h */ class Bar { /* whatever */ }; Since you don't actually make use of Bar objects in H1 (you only indicate that Run, defined in the .cpp file, will use Bar _in the .cpp file_), you don't need the header. So you could make H1 look like this instead: /* H1.h */ class Bar; // forward declare class Foo { public: void Run(Bar* bar); }; Because you didn't use/store Bar (you only mentioned a pointer parameter), you only need to let the compiler know the name, hence the forward declaration. The cpp file, however, will need to #include "H2.h" That is very informal... You might get some more complete descriptions from others here. Aside from circular dependencies, this can help reduce compile time, so it's a nice thing to do. Also, you might consider that such a circular dependency as you describe can often, though not always, indicate a design flaw. Consider your design and see if there are ways to simplify.
  11. mossmoss

    What the f? (C++)

    An L after a number also forces it to be a long (vs an int), and UL is an unsigned long.
  12. Sounds like you want a hash function.
  13. Learn either one... they're pretty similar, so having learned one, the other will be easy to figure out. May also depend on what API you are programming to... DirectX? I think you have to use HLSL. OpenGL, I believe, uses Cg... though I don't know offhand if that is set in stone.
  14. First, get this document, "What Every Computer Scientist Should Know About Floating-Point Arithmetic": http://www.physics.ohio-state.edu/~dws/grouplinks/floating_point_math.pdf Probably a _lot_ more than you want right now, but a good document to have on hand. Second, decent information here: http://en.wikipedia.org/wiki/IEEE_754 It's hard to summarize floating-points... I'd suggest looking at the wikipedia page for a brief overview of how values are represented. Super-briefly, you could have values up to approximately 2^127. Freaking huge. And values down to 2^-126, freakin' small. But there's a price; not every value can be exactly represented. Most values are going to get rounded to the nearest value that can be exactly represented. Additionally, the density of values that can be represented using floating-point is not constant. As an example, the number of integers between 0 and 100 (using an int) is exactly the same as the number of integers between 1,000,000 and 1,000,100. That is not true of floating-point. IIRC, as the magnitude of your f.p. exponent increases, the numbers spread out. Which means if you try to use the full range of a float for your zone, as things move further out from the center of the zone, they'd start jumping. Depending on exactly what you want to do, it may be better to represent certain values with fixed-point rather than floating-point. (In case you're not familiar, fixed-point uses integers and integer arithmetic.) You'll have a well-known range and even distribution.
  15. mossmoss

    Polymorphic sizeof() Operator?

    sizeof alone will not work polymorphically; it's not actually a function (i.e. it is determined at compile-time, not run-time). I can think of a couple ways of getting the size, but without knowing exactly how/when you need your size, I don't know which is appropriate. One way: class A { public: virtual size_t ClassSize() const { return sizeof(A); } // rest of A }; class B : public A { public: virtual size_t ClassSize() const { return sizeof(B); } // rest of B };
  16. mossmoss

    Transform matrix calculation

    Quote:Original post by tconkling So it seems like a game engine ends up having to perform model transforms twice for each object in the game -- once in hardware (inexpensive) while drawing transformed polys to the screen, and once in software (expensive) for engine operations unrelated to drawing. You'll probably stall trying to get matrices back from the GPU. And your CPU calculated matrices are probably not as expensive as you think. A profiler is your friend. If you do find your matrix/matrix or vector/matrix multiplications are costly, then use your library's functions (or write your own) to do these ops using the CPU's vector capabilities (i.e. SSE, VMX, whatever).
  17. Quote:Original post by discman1028 Quote:Original post by mossmoss Personally, I would avoid COW unless you first determined it necessary. (That is, you've profile your code, and have determined the copy constructor for your class is too slow or using too much memory for identical copies.) Even so, I might try alternatives... COW may be a premature optimization, one you don't really need, especially since memory allocators, caches, RAM sizes, etc are not as pathetic as they once were. COW can be tricky to get right, especially if you're doing anything threaded. Not to say it should never be used... But I wouldn't bother unless you've identified it as the best solution to an existing problem. Well, in this case I know it is needed, up front. The data sets will be distributed over ethernet for processing elsewhere to speed up computations. Any allocation more than necessary will result in seconds of extra time. Seconds of extra time out of how much time?
  18. mossmoss

    Random numbers, different platforms

    If you don't want to include boost, and you don't care about statistical randomness, you can implement a linear congruential generator very easily. namespace { const uint32 kA = 1664525; const uint32 kB = 1013904223; uint32 gSeed; } void seedRand(uint32 seed) { gSeed = seed; } uint32 genRand() { gSeed = kA * gSeed + kB; return gSeed; } Some values of kA and kB are better than others... Plenty of research out there. However, no LCG is going to be statistically good; you wouldn't want to use this for security reasons or gambling type stuff (where people are putting down $$$). Benefits of LCG: trivial and fast. And it'll be cross-platform, and repeatable if everyone uses the same initial seed.
  19. Personally, I would avoid COW unless you first determined it necessary. (That is, you've profile your code, and have determined the copy constructor for your class is too slow or using too much memory for identical copies.) Even so, I might try alternatives... COW may be a premature optimization, one you don't really need, especially since memory allocators, caches, RAM sizes, etc are not as pathetic as they once were. COW can be tricky to get right, especially if you're doing anything threaded. Not to say it should never be used... But I wouldn't bother unless you've identified it as the best solution to an existing problem.
  20. mossmoss

    Iterators are pointers?

    Quote:Original post by xDan After removing elements from before this one, does the iterator still remain valid? Is an iterator like a pointer to the data rather than an index? Quoted from http://www.sgi.com/tech/stl/List.html: Lists have the important property that insertion and splicing do not invalidate iterators to list elements, and that even removal invalidates only the iterators that point to the elements that are removed. The ordering of iterators may be changed (that is, list<T>::iterator might have a different predecessor or successor after a list operation than it did before), but the iterators themselves will not be invalidated or made to point to different elements unless that invalidation or mutation is explicit. Note that this does not apply to vectors, deques... only the list.
  21. Providing the errors will help people here to diagnose your problem. In any case, std::string and ci_string are two different types; they start from the same basic_string template, but the template parameters are different, so these two types are considered different by the compiler. (You may know yourself that they are internally identical, but the compiler can't easily know that.) You need a conversion method. One way to do this without changing existing definitions is like this: ci_string MakeCIString(const std::string& s) { return ci_string(s.c_str()); } std::string normalString("Hello, world!"); ci_string caseInsensitive = MakeCIString(normalString); The compiler should be able to optimize this by inlining and potentially the return-value optimization (though I don't remember the specific circumstances to which that applies). Another way would be to change how you define ci_string, by inheritance rather than a typedef, and add a conversion constructor: class ci_string : public std::basic_string<char,ignorecase_traits> { public: ci_string(const std::string& s) { /* behaviour similar to copy constructor */ } }; std::string normalString("Hello, world!"); ci_string caseInsensitive = normalString;
  22. What superpig said, or if possible make it a single-pass technique and do your combination in shader.
  23. mossmoss

    Template woes!

    Move CVectorT::Transform(const CMatrixT&) to CMatrixT::Transform(const CVectorT&). Do you really need all that templatization? (And the C...T naming scheme?)
  24. Asking which way is better without providing context is like asking which subway line gets you to where you want to go without actually knowing where you want to go. Both ideas could work, but choosing one or the other (or some other way) depends on your needs. For example, let's say you have lots of processing power but little storage space. Keeping only a height map is going to be more compact than a mesh, even if the latter is compressed. On the other hand, if you have tons of storage space but want to minimize processing, then having the mesh ready to go might be a better way. Additionally, what other needs do you have? Physics? Shadows? What else? You may find these are easier or harder depending on the model. So ask yourself the question, "What do I need to do with the data?", then examine both ideas and how difficult it would be to satisfy each of those needs with each model. Then choose your model.
  25. mossmoss

    C++ puzzle

    Line 11 creates a single C object, accessed via pointer c. Line 12 treats c as an array; using [0] gets you the first (and, in this case, the only) C object. Then you attempt to assign an integer; however, there is no integer assignment method. So what happens? Line 4 is a constructor that takes an int (size_t), and since it is not explicit, it gets used as a conversion constructor. So a new temporary C is created -- via C(1024) -- and then is assigned to c[0]. You have no assignment operator, which means that members of the class are straight assigned. (That is, c[0].buf = C(1024).buf). FIRST PROBLEM: you just leaked memory created from *c. Then the temporary gets deleted; SECOND PROBLEM: you just deleted memory that is still being referenced (now by *c). When *c is deleted on line 13, you get a double-deletion.
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net 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!