Good question, D... these are actually generated on my old home development PC. And when I say old, I mean old! Athlon dual core, 2GB RAM, nVidia 8800 GTX's in SLI, dual Velociraptor hd's, running 32-bit Windows XP! The thing is, this is the most reliable PC I have ever owned hence I'm reluctant to bin it! I also know that if my code works well on this machine then it should run a fair bit nicer on something more modern. For the record, the ~1.3 million poly head rendered in around 5 minutes on my work PC.
Thanks Russ, glad you like them mate. Next time we meet up I'll talk you through the process... LOL! In a nutshell it all boils down to physics and mathematics (lots of linear algebra and trigonometry) being used to simulate rays of light hitting objects, and then creating an image from that process. I can post up my code if it helps?!?!
Clever idea! Would be interesting to see your results on those dedicated external graphics card units!
If the head takes around 5mins on your work PC - what times are we looking at on your old home PC for comparison?
D.
With exactly the same settings (resolution, antialiasing, camera position, etc.) that head took 52 minutes to render. But there are several optimisations I will look to put in at some point in the future.If the head takes around 5mins on your work PC - what times are we looking at on your old home PC for comparison?
Thanks mate. I just wish I could send you some money right now and take that system off your hands! LOL!Awesome work Andy!
Set aside a quiet couple of years and I'll ring you up to speed mate Sadly I spent far too much time growing up in front of a computer instead of tinkering with cars... could have been a whole different story otherwise! I do admit I'm extremely lucky though being able to enjoy this stuff as a hobby and a profession. Even if it is a bit geeky and sad.I tihnk you will need to be doing a whole lotta explaining to get my head around it lol
Andy's home computer has the processing power of the computer in the batcave, NASA, and that smart thing out of I-Robot
Cool renders, mate - very bling for bullets! They look to be quite a high polygon count, too?
Thanks mate - glad you like it. In all truth the credit must go to whoever created the 3D model as they've done a great job. Mind you, I'm more than happy with how the shading and lighting algorithms work on this particular model. I think I might see where I can take it... (time permitting as always!)That looks ace mate. Need these things in real time!
Tessellation goes along way to emulate more realistic light sources I've noticed recently
The chrome texture works well on those to be fair, especially with the colouring applied. I was wondering whether or not you'd created a loft'ed object rather than messing around with segmented cylinders. For such low poly items they give the impression of higher counts.Cheers dude yeah I wanted them to look like bullets you would display I Was playing around with a chrome texture Made seeing how versatile it is. The bullets themselves won't be that high of a count (I never checked) but they where made from a spline lofted into the 3D shape probably sub 300 polys dare I say sub 200!
Hi mate - the render engine is written in C++ (I usual Microsoft Visual Studio as my integrated development environment). It could indeed be adapted to work as a plug-in for Max/Maya (or other tools) but for now it's mainly a play thing. It would need a fair bit of work and tidying up to get it into a state whereby I'd be happy to release it. As it's a "play thing" I've not got any formal plan or design and I'm simply having fun with it as I go along.Seriously jealous of your coding skills . Out of interest what are you using to code this render engine? Would you maybe code it to work with max/maya at some stage or is it just a play thing? Would you sell it once its finished or would it be a constant development? Also would you post a little code snippet of what you have wrote maybe 10 lines or so? I'm interested to see what the code looks like!
if (pPrim->GetReceivesLight())
{
//>>
Mat33 matTBN;
matTBN.SetIdentity();
bool bUseTBN = false;
if (pPrim->GetType() == Primitive::PRIMTYPE_TRIANGLE)
{
if (pPrim->GetMaterial()->GetNormalTexture())
{
PrimitiveTriangle* pTri = (PrimitiveTriangle*)pPrim;
if (pTri)
{
pTri->GetTBNMatrix(&matTBN);
bUseTBN = true;
}
}
}
//>>
// Trace contributing lights
for (unsigned int lightIndex=0; lightIndex<mpScene->GetNumLights(); ++lightIndex)
{
Primitive* pLight = mpScene->GetLight(lightIndex);
Vec3 L;
//
// Determine shadow/shading term
//
float shadowTerm = _CalculateShadowTerm(pLight, intersectionPt, L);
//
// Apply TBN matrix?
//
if (bUseTBN)
{
L = L * matTBN;
}
if (shadowTerm > 0.0f)
{
Vec3 N = pPrim->GetNormal(intersectionPt);
const float cAttenuation = 1.0f;
//
// Calculate diffuse shading
//
if (pPrim->GetMaterial()->GetDiffuseIntensity() > 0.0f)
{
float dotProd = (N ^ L);
if (dotProd > 0.0f)
{
float diffuse = dotProd * pPrim->GetMaterial()->GetDiffuseIntensity() * shadowTerm;
accumColour += diffuse * primDiffuseColour * pLight->GetMaterial()->GetDiffuseColour() * cAttenuation;
}
}
//
// Calculate specular
//
if (pPrim->GetMaterial()->GetSpecularIntensity() > 0.0f)
{
Vec3 V = ray.GetDirection() * matTBN;
Vec3 R = L - (2.0f * (N ^ L)) * N;
float dotProd = (V ^ R);
if (dotProd > 0.0f)
{
float specular = powf(dotProd, pPrim->GetMaterial()->GetSpecularPower()) * pPrim->GetMaterial()->GetSpecularIntensity() * shadowTerm;
accumColour += specular * primSpecularColour * pLight->GetMaterial()->GetDiffuseColour() * cAttenuation;
}
}
}
}
}
else
{
accumColour += primDiffuseColour;
}
if (mbEnableReflections)
{
//
// Calculate reflection
//
float reflection = pPrim->GetMaterial()->GetReflection();
if ((reflection > 0.0f) && (traceDepth < mMaxTraceDepth))
{
Vec3 N = pPrim->GetNormal(intersectionPt);
Vec3 R = ray.GetDirection() - (2.0f * (ray.GetDirection() ^ N) * N);
Vec4 reflColour(0.0f, 0.0f, 0.0f, 0.0f);
float reflDist;
RayTrace(Ray(intersectionPt + (R * scmEpsilon), R, ++mCurRayID), reflColour, traceDepth + 1, refractionIndex, reflDist);
accumColour += reflection * reflColour * primDiffuseColour;
}
}
if (mbEnableRefractions)
{
//
// Calculate refractions
//
float refraction = pPrim->GetMaterial()->GetRefraction();
if ((refraction > 0.0f) && (traceDepth < mMaxTraceDepth))
{
float currRefrIndex = pPrim->GetMaterial()->GetRefractionIndex();
float n = refractionIndex / currRefrIndex;
Vec3 N = pPrim->GetNormal(intersectionPt) * (float)result;
float cosI = -(N ^ ray.GetDirection());
float cosT2 = 1.0f - n * n * (1.0f - cosI * cosI);
if (cosT2 > 0.0f)
{
Vec3 T = (n * ray.GetDirection()) + (n * cosI - sqrtf(cosT2)) * N;
Vec4 refrColour(0.0f, 0.0f, 0.0f, 0.0f);
float refrDist;
RayTrace(Ray(intersectionPt + (T * scmEpsilon), T, ++mCurRayID), refrColour, traceDepth + 1, currRefrIndex, refrDist);
// Apply Beer's Law
Vec4 absorbance = primDiffuseColour * 0.15f * -refrDist;
Vec4 transparency = Vec4(expf(absorbance.mX), expf(absorbance.mY), expf(absorbance.mZ));
accumColour += refrColour * transparency;
}
}
}
No, it didn't sound stupid at all mate. I can fully appreciate where you are coming from and understand why you would want to control the 'recursion' and resulting stack yourself. It is possibly a route I will take at some point when looking to optimise the raytracer as I'm beginning to think that unmanaged recursive algorithms might not translate so well when looking to take advantage of GPU processing power through CUDA and similar languages. It's a little too early in the day for that though and I'm not sure I want to get that serious with this project just yet (if that makes sense).I realise what I wrote sounded stupid, when I said "recursive?" I actually wasn't surprised that it was a recursive algorithm (it obviously is), I was just surprised that you implemented it as recursive, but if you limit the depth that the stack could go then it's obviously not a problem.
Yes, I have to agree with you here as I'm always a bit wary when it comes to recursive code! Especially when working with data sets where data size, resource and processing requirements can grow exponentially. From your obvious knowledge and experience (and comments) I would hazard a guess that you've experienced the pain of unmanaged recursive code once or twice!Maybe it's because I was always nervous of recursive code because of the type of data I was processing.