You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm trying to create a minimal sample for OSL because existing samples (testshade, testrender) are quite complex.
This isn't yet fully compiling code. I'm hoping to get some help with this one, even just comments that point to missing things or explain things. The end result can then hopefully be added into OSL.
Edit1: I updated the code. Now it compiles but crashes at a call to Shader().
Edit2: Now its working code but closure parsing is very basic.
#include <iostream>
#include <OSL/oslexec.h>
#include <OSL/oslcomp.h>
#include <OSL/oslclosure.h>
#include <OSL/oslconfig.h>
#include <OSL/rendererservices.h>
#include <OSL/genclosure.h>
#include <OSL/dual_vec.h>
#if OSL_USE_BATCHED
# include <OSL/batched_shaderglobals.h>
#endif
//#include <OSL/encodedtypes.h>
//#include <OSL/hashes.h>
//#include <OSL/journal.h>
//#include <OSL/shaderglobals.h>
#include "OpenImageIO/filesystem.h"
using namespace OSL;
// Supported closures and parameters
struct EmptyParams {};
enum ClosureIDs {
DIFFUSE_ID
};
struct DiffuseParams {
OSL::Vec3 N;
};
void register_closures(OSL::ShadingSystem* ss)
{
// "Describe the memory layout of each closure type to the OSL runtime"
constexpr int MaxParams = 32;
struct BuiltinClosures {
const char* name;
int id;
OSL::ClosureParam params[MaxParams]; // "upper bound"
};
// Closures with support built into OSL, connected by the 1st string
BuiltinClosures supported[] = {
{ "diffuse", DIFFUSE_ID,
{ CLOSURE_VECTOR_PARAM(DiffuseParams, N),
CLOSURE_FINISH_PARAM(DiffuseParams) } },
};
// Closure registration here enables that type of closure, when executing or compiling a shader
for (const BuiltinClosures& c : supported)
ss->register_closure(c.name, c.id, c.params, nullptr, nullptr);
}
/// Custom RendererServices
class OSLMaterial : public RendererServices {
public:
OIIO::ErrorHandler& errhandler() const { return *m_errhandler; }
/// Turn information at hitpoint into ShaderGlobals for OSL
void globals_from_hit(ShaderGlobals& sg)
{
sg.P = {0.0f,0.0f,0.0f}; // surface pos
sg.dPdx = {0.0f,0.0f,0.0f};
sg.dPdy = {0.0f,0.0f,0.0f};
sg.dPdz = {0.0f,0.0f,0.0f}; // for volume shading only
sg.I = {0.0f,0.0f,-1.0f}; // incident ray
sg.dIdx = {0.0f,0.0f,0.0f};
sg.dIdy = {0.0f,0.0f,0.0f};
sg.N = {0.0f,0.0f,1.0f}; // shading normal
sg.Ng = {0.0f,0.0f,1.0f}; // true geometric normal
sg.u = 0.5f; // 2D surface parameter u, and its differentials.
sg.dudx = 0.0f;
sg.dudy = 0.0f;
sg.v = 0.5f; // 2D surface parameter v, and its differentials.
sg.dvdx = 0.0f;
sg.dvdy = 0.0f;
// Surface tangents: derivative of P with respect to surface u and v.
sg.dPdu = {1.0f,0.0f,0.0f};
sg.dPdv = {0.0f,1.0f,0.0f};
sg.time = 0.0f;
sg.dtime = 0.001f;
// Velocity vector: derivative of position P with respect to time.
sg.dPdtime = {0.0f,0.0f,0.0f};
// For lights or light attenuation shaders: the point being illuminated (???)
sg.Ps = {0.0f,0.0f,0.0f};
sg.dPsdx = {0.0f,0.0f,0.0f};
sg.dPsdy = {0.0f,0.0f,0.0f};
// Renderer user pointers
sg.renderstate= NULL;
sg.tracedata=NULL;
sg.objdata=NULL;
sg.renderer = this;
sg.raytype = 1; // 1 stands for camera ray?
sg.flipHandedness = 0;
sg.backfacing = 0;
// output closure, needs to be null initialized
sg.Ci=NULL;
}
/// Allow to evaluate background from OSL TODO connect/enable this somehow
void eval_background(const Dual2<Vec3>& dir, ShadingContext* ctx, int bounce);
// ShaderGroupRef storage
std::vector<ShaderGroupRef>& shaders() { return m_shaders; }
std::vector<ShaderGroupRef> m_shaders;
private:
std::unique_ptr<OIIO::ErrorHandler> m_errhandler;
};
int main(void)
{
// Renderer for OSL
OSLMaterial* oslmat = new OSLMaterial();
// New ShadingSystem
// Custom texturesystem TODO document what this does and how to customize
OSL::TextureSystem* texturesys = TextureSystem::create();
OSL::ShadingSystem* ss = new ShadingSystem(oslmat, texturesys, &oslmat->errhandler());
register_closures(ss);
// New ShadingContext
OSL::PerThreadInfo* thread_info = ss->create_thread_info();
OSL::ShadingContext* context = ss->get_context(thread_info);
// Construct OSL ShaderGlobals from hitpoint information
OSL::ShaderGlobals globals; // This holds both hitpoint input and closure output, and other data
// Renderer hit a surface to be shaded, construct ShaderGlobals from information at hitpoint
oslmat->globals_from_hit(globals);
// Create one shader
std::string sourcecode;
std::string oslfilename = "matte.osl";
OIIO::Filesystem::read_text_file(oslfilename, sourcecode);
std::string osobuffer;
OSLCompiler compiler;
std::vector<std::string> options;
// Compile sourcecode and put the result into osobuffer
if (!compiler.compile_buffer(sourcecode, osobuffer, options))
{
std::cerr << "Could not compile \"" << oslfilename << "\"\n";
exit(EXIT_FAILURE);
}
// Make osobuffer available to ss->Shader() call. "Load compiled shader (oso) from a memory buffer, overriding shader lookups in the shader search path"
if (!ss->LoadMemoryCompiledShader(oslfilename, osobuffer))
{
std::cerr << "Could not load compiled jbuffer from \"" << oslfilename << "\"\n";
exit(EXIT_FAILURE);
}
// Create a new shader group
oslmat->m_shaders.emplace_back();
oslmat->m_shaders[0] = ss->ShaderGroupBegin ("my shader group");
ShaderGroupRef group = oslmat->m_shaders[0];
// These parameters are from matte.osl
float Kd = 1.0f;
OSL::Color3 Cs = { 1.0f,0.1f,0.1f };
// Supply the parameters
ss->Parameter (*group, "Kd", OSL::TypeDesc::TypeFloat, &Kd);
ss->Parameter (*group, "Cs", OSL::TypeDesc::TypeColor, &Cs);
// Create a shader
ss->Shader(*group, "matte.osl", oslfilename, "mylayer");
ss->ShaderGroupEnd(*group);
// Run the shader that was just created
ss->execute(context, *group, globals);
// Read closure output that resides in globals
// All output closures. Documented in include/OSL/oslclosure.h
const ClosureColor* closure = globals.Ci;
if (closure)
{
std::cout << "we have output closure!" << std::endl;
// Single primitive closure component. Documented in include/OSL/oslclosure.h
const ClosureComponent* comp = closure->as_comp();
switch (comp->id)
{
case DIFFUSE_ID:
{
std::cout << "diffuse closure!" << std::endl;
DiffuseParams p = *comp->as<DiffuseParams>();
// Closure color
std::cout << "ClosureComponent weight / closure color: " << comp->w[0] << " " << comp->w[1] << " " << comp->w[2] << std::endl;
// Closure direction
std::cout << "DiffuseParams N / closure direction: " << p.N[0] << " " << p.N[1] << " " << p.N[2] << std::endl;
}
break;
default:
std::cout << "unknown closure: " << (int)(closure->id) << std::endl;
break;
}
}
ss->release_context(context);
ss->destroy_thread_info(thread_info);
// TODO more cleanup maybe
return 0;
}
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
I'm trying to create a minimal sample for OSL because existing samples (testshade, testrender) are quite complex.
This isn't yet fully compiling code. I'm hoping to get some help with this one, even just comments that point to missing things or explain things. The end result can then hopefully be added into OSL.
Edit1: I updated the code. Now it compiles but crashes at a call to Shader().
Edit2: Now its working code but closure parsing is very basic.
Beta Was this translation helpful? Give feedback.
All reactions