Beispiel #1
0
QString
ShaderFactory::genDefaultSliceShaderString(bool bit16,
					   bool lighting,
					   bool emissive,
					   QList<CropObject> crops,
					   bool peel, int peelType,
					   float peelMin, float peelMax, float peelMix)
{
  bool cropPresent = false;
  bool tearPresent = false;
  bool viewPresent = false;
  bool glowPresent = false;
  for(int i=0; i<crops.count(); i++)
    if (crops[i].cropType() < CropObject::Tear_Tear)
      cropPresent = true;
    else if (crops[i].cropType() < CropObject::View_Tear)
      tearPresent = true;
    else if (crops[i].cropType() < CropObject::Glow_Ball)
      viewPresent = true;
    else
      glowPresent = true;

  for(int i=0; i<crops.count(); i++)
    if (crops[i].cropType() >= CropObject::View_Tear &&
	crops[i].cropType() <= CropObject::View_Block &&
	crops[i].magnify() > 1.0)
      tearPresent = true;

  bool pathCropPresent = PathShaderFactory::cropPresent();
  bool pathViewPresent = PathShaderFactory::blendPresent();

  float lastSet = (Global::lutSize()-1.0)/Global::lutSize();
  QString shader;

  shader =  "#extension GL_ARB_texture_rectangle : enable\n";
  shader += "varying vec3 pointpos;\n";
  shader += "uniform sampler2D lutTex;\n";
  shader += "uniform sampler2DRect dataTex;\n";
  shader += "uniform sampler1D paintTex;\n";

  shader += "uniform float tfSet;\n";
  shader += "uniform vec3 delta;\n";
  shader += "uniform vec3 eyepos;\n";
  shader += "uniform vec3 lightpos;\n";
  shader += "uniform float ambient;\n";
  shader += "uniform float diffuse;\n";
  shader += "uniform float specular;\n";
  shader += "uniform float speccoeff;\n";
  shader += "uniform int gridx;\n";
  shader += "uniform int tsizex;\n";
  shader += "uniform int tsizey;\n";
  shader += "uniform float depthcue;\n";

  shader += "uniform sampler2DRect lightTex;\n";
  shader += "uniform int lightgridx;\n";
  shader += "uniform int lightgridy;\n";
  shader += "uniform int lightgridz;\n";
  shader += "uniform int lightnrows;\n";
  shader += "uniform int lightncols;\n";
  shader += "uniform int lightlod;\n";

  shader += "uniform sampler2DRect pruneTex;\n";
  shader += "uniform int prunegridx;\n";
  shader += "uniform int prunetsizex;\n";
  shader += "uniform int prunetsizey;\n";
  shader += "uniform float prunelod;\n";
  shader += "uniform int zoffset;\n";

  shader += "uniform vec2 dataMin;\n";
  shader += "uniform vec2 dataSize;\n";
  shader += "uniform int tminz;\n";

  shader += "uniform int lod;\n";
  shader += "uniform vec3 dirFront;\n";
  shader += "uniform vec3 dirUp;\n";
  shader += "uniform vec3 dirRight;\n";

  shader += "uniform vec3 brickMin;\n";
  shader += "uniform vec3 brickMax;\n";

  shader += genTextureCoordinate();

  if (tearPresent) shader += TearShaderFactory::generateTear(crops);
  if (cropPresent) shader += CropShaderFactory::generateCropping(crops);
  if (glowPresent) shader += GlowShaderFactory::generateGlow(crops);  
  if (viewPresent) shader += BlendShaderFactory::generateBlend(crops);
  if (pathCropPresent) shader += PathShaderFactory::applyPathCrop();
  if (pathViewPresent) shader += PathShaderFactory::applyPathBlend();

  shader += "void main(void)\n";
  shader += "{\n";

  shader += "  vec3 lightcol = vec3(1.0,1.0,1.0);\n";

  shader += "  vec3 texCoord = gl_TexCoord[0].xyz;\n";

  shader += "if (any(lessThan(texCoord,brickMin)) || any(greaterThan(texCoord, brickMax)))\n";
  shader += "  discard;\n";

  if (crops.count() > 0)
    {
      shader += "  vec3 otexCoord = texCoord;\n";
      shader += "  float feather = 1.0;\n";
    }
  else
    {
      if (pathCropPresent)
	shader += "  float feather = 1.0;\n";
      if (pathViewPresent)
	shader += "  vec3 otexCoord = texCoord;\n";
    }

  if (tearPresent)
    {
      shader += "vec4 tcf = dissect(texCoord);\n";
      shader += "texCoord = tcf.xyz;\n";
      shader += "feather *= tcf.w;\n";
    }
  if (cropPresent) shader += "feather *= crop(texCoord, true);\n";
  if (pathCropPresent) shader += "feather *= pathcrop(texCoord, true);\n";

  shader += "texCoord.x = 1.0 + float(tsizex-2)*(texCoord.x-dataMin.x)/dataSize.x;\n";
  shader += "texCoord.y = 1.0 + float(tsizey-2)*(texCoord.y-dataMin.y)/dataSize.y;\n";

//----------------------------------------------------------
// Manipulate z-coordinate for non linear depth levels
//  int levels = 4;
//  float origT[10], newT[10];
//  origT[0] = 00.00;  newT[0] = 00.0;
//  origT[1] = 01.20;  newT[1] = 11.0;
//  origT[2] = 04.00;  newT[2] = 23.0;
//  origT[3] = 37.62;  newT[3] = 56.0;
//  origT[4] = 62.00;  newT[4] = 62.0;
//
//  for(int o=0; o<levels; o++)
//    {
//      if (o > 0)
//	shader += "else ";
//      shader += QString("if (texCoord.z >= float(%1) && texCoord.z < float(%2))\n").\
//	arg(origT[o]).\
//	arg(origT[o+1]);
//      shader += "  {\n"; 
//
//      shader += QString("    float tz = (texCoord.z-float(%1))/(float(%2)-float(%1));\n").\
//	arg(origT[o]).							\
//	arg(origT[o+1]);
//
//      shader += QString("    texCoord.z = float(%1) + tz * (float(%2)-float(%1));\n").\
//	arg(newT[o]).\
//	arg(newT[o+1]);
//      shader += "  }\n";
//    }
//----------------------------------------------------------
  
  shader += "texCoord.z = 1.0 + (texCoord.z-float(tminz))/float(lod);\n";

  shader += genVgx();

  //----------------------------------
  shader += " if (lightlod > 0)\n";
  shader += "   {\n"; // calculate light color
  shader += "     vec3 lc;\n";
  shader += "     vec2 pvg = texCoord.xy / prunelod;\n";
  shader += "     pvg /= vec2(lightlod,lightlod);\n";
  shader += "     vec2 pvg0 = getTextureCoordinate(int(float(zoffset+slice)/prunelod)/lightlod, ";
  shader += "            lightncols, lightgridx, lightgridy, pvg);\n";
  shader += "     vec2 pvg1 = getTextureCoordinate(int(float(zoffset+slice+1)/prunelod)/lightlod, ";
  shader += "            lightncols, lightgridx, lightgridy, pvg);\n";
  shader += "     vec3 lc0 = texture2DRect(lightTex, pvg0).xyz;\n";
  shader += "     vec3 lc1 = texture2DRect(lightTex, pvg1).xyz;\n";
  shader += "     lightcol = mix(lc0, lc1, slicef);\n";
  shader += "     lightcol = 1.0-pow((vec3(1,1,1)-lightcol),vec3(lod,lod,lod));\n";
  shader += "   }\n";
  shader += " else\n";
  shader += "   lightcol = vec3(1.0,1.0,1.0);\n";
  //----------------------------------

  if (peel || lighting || !Global::use1D())
    shader += getNormal();


  if (bit16)
    {
      shader += "int h0 = int(65535.0*vg.x);\n";
      shader += "int h1 = h0 / 256;\n";
      shader += "h0 = int(mod(float(h0),256.0));\n";
      shader += "float fh0 = float(h0)/256.0;\n";
      shader += "float fh1 = float(h1)/256.0;\n";

      shader += QString("vg.xy = vec2(fh0, fh1*%1);\n").arg(1.0/Global::lutSize());
    }
  else
    {
      if (Global::use1D())
	shader += "  vg.y = 0.0;\n";
      else
	shader += QString("  vg.y = grad*%1;\n").arg(1.0/Global::lutSize());
    }


  shader += "  vg1 = vg;\n";
  shader += "  vg.y += tfSet;\n";
  shader += "  gl_FragColor = texture2D(lutTex, vg.xy);\n";

  if (Global::emptySpaceSkip())
    {
      shader += "  gl_FragColor.rgba = mix(vec4(0.0,0.0,0.0,0.0), gl_FragColor.rgba, prunefeather.x);\n";
      if (PruneHandler::blend())
	shader += blendVolume();
      else
	shader += tagVolume();
    }


  if (tearPresent || cropPresent || pathCropPresent)
    shader += "  gl_FragColor.rgba = mix(gl_FragColor.rgba, vec4(0.0,0.0,0.0,0.0), feather);\n";

  if (viewPresent) shader += "  blend(otexCoord, vg, gl_FragColor);\n";
  
  if (pathViewPresent) shader += "pathblend(otexCoord, vg, gl_FragColor);\n";
  

//---------------------------------
  if (Global::emptySpaceSkip())
    {
      shader += "if (delta.x > 1.0)\n";
      shader += "  { gl_FragColor = vec4(vg.x*step(0.001,gl_FragColor.a),";
      shader += "gl_FragColor.a, prunefeather.z, 1.0); return; }\n";
    }
  else
    {
      shader += "if (delta.x > 1.0)\n";
      shader += "  { gl_FragColor = vec4(vg.x*step(0.001,gl_FragColor.a),";
      shader += "gl_FragColor.a, 0.0, 1.0); return; }\n";
    }
//---------------------------------

//------------------------------------
  shader += "gl_FragColor = 1.0-pow((vec4(1,1,1,1)-gl_FragColor),";
  shader += "vec4(lod,lod,lod,lod));\n";
//------------------------------------

  shader += "\n";
  shader += "  if (gl_FragColor.a < 0.005)\n";
  shader += "	discard;\n";

  if (lighting)
    shader += addLighting();

  shader += genPeelShader(peel, peelType,
			  peelMin, peelMax, peelMix,
			  lighting);

  if (emissive)
    {
      shader += QString("  vg1.y += float(%1);\n").arg(lastSet);
      shader += "  gl_FragColor.rgb += texture2D(lutTex, vg1.xy).rgb;\n";
    }

  // -- depth cueing
  shader += "  gl_FragColor.rgb *= depthcue;\n";

  if (glowPresent) shader += "  gl_FragColor.rgb += glow(otexCoord);\n";

  shader += "  gl_FragColor = clamp(gl_FragColor, vec4(0.0,0.0,0.0,0.0), vec4(1.0,1.0,1.0,1.0));\n";

  shader += "}\n";

  return shader;
}
Beispiel #2
0
QString
ShaderFactory::genDefaultSliceShaderString(bool bit16,
					   bool lighting,
					   bool emissive,
					   QList<CropObject> crops,
					   bool peel, int peelType,
					   float peelMin, float peelMax, float peelMix)
{
  bool cropPresent = false;
  bool tearPresent = false;
  bool viewPresent = false;
  bool glowPresent = false;
  for(int i=0; i<crops.count(); i++)
    if (crops[i].cropType() < CropObject::Tear_Tear)
      cropPresent = true;
    else if (crops[i].cropType() < CropObject::View_Tear)
      tearPresent = true;
    else if (crops[i].cropType() < CropObject::Glow_Ball)
      viewPresent = true;
    else
      glowPresent = true;

  for(int i=0; i<crops.count(); i++)
    if (crops[i].cropType() >= CropObject::View_Tear &&
	crops[i].cropType() <= CropObject::View_Block &&
	crops[i].magnify() > 1.0)
      tearPresent = true;

  bool pathCropPresent = PathShaderFactory::cropPresent();
  bool pathViewPresent = PathShaderFactory::blendPresent();

  float lastSet = (Global::lutSize()-1.0)/Global::lutSize();
  QString shader;

  shader =  "#extension GL_ARB_texture_rectangle : enable\n";
  shader += "varying vec3 pointpos;\n";
  shader += "uniform sampler2D lutTex;\n";
  shader += "uniform sampler2DRect dataTex;\n";
  shader += "uniform sampler1D paintTex;\n";

  shader += "uniform float tfSet;\n";
  shader += "uniform vec3 delta;\n";
  shader += "uniform vec3 eyepos;\n";
  shader += "uniform vec3 lightpos;\n";
  shader += "uniform float ambient;\n";
  shader += "uniform float diffuse;\n";
  shader += "uniform float specular;\n";
  shader += "uniform float speccoeff;\n";
  shader += "uniform int gridx;\n";
  shader += "uniform int tsizex;\n";
  shader += "uniform int tsizey;\n";
  shader += "uniform float depthcue;\n";

  shader += "uniform sampler2DRect lightTex;\n";
  shader += "uniform int lightgridx;\n";
  shader += "uniform int lightgridy;\n";
  shader += "uniform int lightgridz;\n";
  shader += "uniform int lightnrows;\n";
  shader += "uniform int lightncols;\n";
  shader += "uniform int lightlod;\n";

  shader += "uniform sampler2DRect pruneTex;\n";
  shader += "uniform int prunegridx;\n";
  shader += "uniform int prunetsizex;\n";
  shader += "uniform int prunetsizey;\n";
  shader += "uniform float prunelod;\n";
  shader += "uniform int zoffset;\n";

  shader += "uniform vec2 dataMin;\n";
  shader += "uniform vec2 dataSize;\n";
  shader += "uniform int tminz;\n";

  shader += "uniform int lod;\n";
  shader += "uniform vec3 dirFront;\n";
  shader += "uniform vec3 dirUp;\n";
  shader += "uniform vec3 dirRight;\n";

  shader += "uniform bool mixTag;\n";

  shader += "uniform vec3 brickMin;\n";
  shader += "uniform vec3 brickMax;\n";

  shader += "uniform int shdlod;\n";
  shader += "uniform sampler2DRect shdTex;\n";
  shader += "uniform float shdIntensity;\n";

  shader += "uniform float opmod;\n";
  shader += "uniform bool linearInterpolation;\n";

  shader += "uniform float dofscale;\n";

  shader += genTextureCoordinate();

  if (tearPresent) shader += TearShaderFactory::generateTear(crops);
  if (cropPresent) shader += CropShaderFactory::generateCropping(crops);
  if (glowPresent) shader += GlowShaderFactory::generateGlow(crops);  
  if (viewPresent) shader += BlendShaderFactory::generateBlend(crops);
  if (pathCropPresent) shader += PathShaderFactory::applyPathCrop();
  if (pathViewPresent) shader += PathShaderFactory::applyPathBlend();

  shader += "void main(void)\n";
  shader += "{\n";

  shader += "  vec3 lightcol = vec3(1.0,1.0,1.0);\n";

  shader += "  vec3 texCoord = gl_TexCoord[0].xyz;\n";

  shader += "if (any(lessThan(texCoord,brickMin)) || ";
  shader += "any(greaterThan(texCoord, brickMax)))\n";
  //shader += "    if (any(lessThan(texCoord,brickMin-vec3(0.5,0.5,0.5))) || ";
  //shader += "    any(greaterThan(texCoord, brickMax+vec3(0.5,0.5,0.5))))\n";
  //shader += "    if (any(lessThan(texCoord,brickMin-vec3(1,1,1))) || ";
  //shader += "    any(greaterThan(texCoord, brickMax+vec3(1,1,1))))\n";
  shader += "  discard;\n";

  if (crops.count() > 0)
    {
      shader += "  vec3 otexCoord = texCoord;\n";
      shader += "  float feather = 1.0;\n";
    }
  else
    {
      if (pathCropPresent)
	shader += "  float feather = 1.0;\n";
      if (pathViewPresent)
	shader += "  vec3 otexCoord = texCoord;\n";
    }

  if (tearPresent)
    {
      shader += "vec4 tcf = dissect(texCoord);\n";
      shader += "texCoord = tcf.xyz;\n";
      shader += "feather *= tcf.w;\n";
    }
  if (cropPresent) shader += "feather *= crop(texCoord, true);\n";
  if (pathCropPresent) shader += "feather *= pathcrop(texCoord, true);\n";

  shader += "texCoord.x = 1.0 + float(tsizex-2)*(texCoord.x-dataMin.x)/dataSize.x;\n";
  shader += "texCoord.y = 1.0 + float(tsizey-2)*(texCoord.y-dataMin.y)/dataSize.y;\n";  
  shader += "texCoord.z = 1.0 + (texCoord.z-float(tminz))/float(lod);\n";

  shader += genVgx();

  shader += "float value = vg.x;\n";

  //----------------------------------
  // this is specifically for nearest neighbour interpolating when upscaling
  // or volume and surface area calculations
  shader += "  if (depthcue > 1.0) vg.x = val0;\n";
  //----------------------------------

  //----------------------------------
  //------------------------------------
  shader += "if (lightlod > 0)\n";
  shader += "  {\n"; // calculate light color
  shader += "    vec2 pvg = texCoord.xy/(prunelod*float(lightlod));\n";	       
  shader += "    int lbZslc = int(float(zoffset+slice)/(prunelod*float(lightlod)));\n";
  shader += "    float lbZslcf = fract(float(zoffset+slice)/(prunelod*float(lightlod)));\n";
  shader += "    vec2 pvg0 = getTextureCoordinate(lbZslc, ";
  shader += "                  lightncols, lightgridx, lightgridy, pvg);\n";
  shader += "    vec2 pvg1 = getTextureCoordinate(lbZslc+1, ";
  shader += "                  lightncols, lightgridx, lightgridy, pvg);\n";	       
  shader += "    vec3 lc0 = texture2DRect(lightTex, pvg0).xyz;\n";
  shader += "    vec3 lc1 = texture2DRect(lightTex, pvg1).xyz;\n";
  shader += "    lightcol = mix(lc0, lc1, lbZslcf);\n";
  shader += "    lightcol = 1.0-pow((vec3(1,1,1)-lightcol),vec3(lod,lod,lod));\n";
  shader += "  }\n";
  shader += "else\n";
  shader += "  lightcol = vec3(1.0,1.0,1.0);\n";

  shader += "if (shdlod > 0)\n";
  shader += "  {\n";
  shader += "     float sa = texture2DRect(shdTex, gl_FragCoord.xy*vec2(dofscale)/vec2(shdlod)).a;\n";
  shader += "     sa = 1.0-smoothstep(0.0, shdIntensity, sa);\n";
  shader += "     sa = clamp(0.1, sa, 1.0);\n";
  shader += "     lightcol *= sa;\n";
  shader += "  }\n";
  //----------------------------------

  if (peel || lighting || !Global::use1D())
    shader += getNormal();


  if (bit16)
    {
      shader += "  int h0 = int(65535.0*vg.x);\n";
      shader += "  int h1 = h0 / 256;\n";
      shader += "  h0 = int(mod(float(h0),256.0));\n";
      shader += "  float fh0 = float(h0)/256.0;\n";
      shader += "  float fh1 = float(h1)/256.0;\n";

      shader += QString("  vg.xy = vec2(fh0, fh1*%1);\n").arg(1.0/Global::lutSize());
    }
  else
    {
      if (Global::use1D())
	shader += "  vg.y = 0.0;\n";
      else
	shader += QString("  vg.y = grad*%1;\n").arg(1.0/Global::lutSize());
    }

  shader += "  vg1 = vg;\n";
  shader += "  vg.y += tfSet;\n";
  shader += "  gl_FragColor = texture2D(lutTex, vg.xy);\n";


  if (Global::emptySpaceSkip())
    {
      shader += "  gl_FragColor.rgba = mix(vec4(0.0,0.0,0.0,0.0), gl_FragColor.rgba, prunefeather.x);\n";
      if (PruneHandler::blend())
	shader += blendVolume();
      else
	shader += tagVolume();
    }


  if (tearPresent || cropPresent || pathCropPresent)
    shader += "  gl_FragColor.rgba = mix(gl_FragColor.rgba, vec4(0.0,0.0,0.0,0.0), feather);\n";

  if (viewPresent) shader += "  blend(false, otexCoord, vg, gl_FragColor);\n";
  
  if (pathViewPresent) shader += "pathblend(otexCoord, vg, gl_FragColor);\n";
  

//---------------------------------
  if (Global::emptySpaceSkip())
    {
      shader += "if (delta.x > 1.0)\n";
      shader += "  { gl_FragColor = vec4(value*step(0.001,gl_FragColor.a),";
      shader += "gl_FragColor.a, prunefeather.z, 1.0); return; }\n";
    }
  else
    {
      shader += "if (delta.x > 1.0)\n";
      shader += "  { gl_FragColor = vec4(value*step(0.001,gl_FragColor.a),";
      shader += "gl_FragColor.a, 0.0, 1.0); return; }\n";
    }
//---------------------------------

//------------------------------------
  shader += "gl_FragColor = 1.0-pow((vec4(1,1,1,1)-gl_FragColor),";
  shader += "vec4(lod,lod,lod,lod));\n";
//------------------------------------

  shader += "\n";
  shader += "  if (gl_FragColor.a < 0.005)\n";
  shader += "	discard;\n";

  if (lighting)
    shader += addLighting();

  shader += genPeelShader(peel, peelType,
			  peelMin, peelMax, peelMix,
			  lighting);

  if (emissive)
    {
      shader += QString("  vg1.y += float(%1);\n").arg(lastSet);
      shader += "  gl_FragColor.rgb += texture2D(lutTex, vg1.xy).rgb;\n";
    }

  // -- depth cueing
  shader += "  gl_FragColor.rgb *= min(1.0,depthcue);\n";

  shader += "  gl_FragColor *= opmod;\n";

  if (glowPresent) shader += "  gl_FragColor.rgb += glow(otexCoord);\n";

  shader += "  gl_FragColor = clamp(gl_FragColor, vec4(0.0,0.0,0.0,0.0), vec4(1.0,1.0,1.0,1.0));\n";

  shader += "}\n";

  return shader;
}
Beispiel #3
0
QString
ShaderFactory::genSliceShadowShaderString(bool bit16,
					  float shadowintensity,
					  float r, float g, float b,
					  QList<CropObject> crops,
					  bool peel, int peelType,
					  float peelMin, float peelMax, float peelMix)
{
  bool cropPresent = false;
  bool tearPresent = false;
  bool viewPresent = false;
  bool glowPresent = false;
  for(int i=0; i<crops.count(); i++)
    if (crops[i].cropType() < CropObject::Tear_Tear)
      cropPresent = true;
    else if (crops[i].cropType() < CropObject::View_Tear)
      tearPresent = true;
    else if (crops[i].cropType() < CropObject::Glow_Ball)
      viewPresent = true;
    else
      glowPresent = true;

  for(int i=0; i<crops.count(); i++)
    if (crops[i].cropType() >= CropObject::View_Tear &&
	crops[i].cropType() <= CropObject::View_Block &&
	crops[i].magnify() > 1.0)
      tearPresent = true;

  bool pathCropPresent = PathShaderFactory::cropPresent();
  bool pathViewPresent = PathShaderFactory::blendPresent();

  QString shader;
  float maxrgb = qMax(r, qMax(g, b));
  if (maxrgb > 1)
    maxrgb = 1.0/maxrgb;
  else
    maxrgb = 1.0;

  shader =  "#extension GL_ARB_texture_rectangle : enable\n";
  shader += "varying vec3 pointpos;\n";
  shader += "uniform sampler2D lutTex;\n";
  shader += "uniform sampler2DRect dataTex;\n";
  shader += "uniform sampler1D paintTex;\n";

  shader += "uniform vec3 eyepos;\n";
  shader += "uniform float tfSet;\n";
  shader += "uniform int gridx;\n";
  shader += "uniform int tsizex;\n";
  shader += "uniform int tsizey;\n";
  shader += "\n";

  shader += "uniform sampler2DRect pruneTex;\n";
  shader += "uniform int prunegridx;\n";
  shader += "uniform int prunetsizex;\n";
  shader += "uniform int prunetsizey;\n";
  shader += "uniform float prunelod;\n";
  shader += "uniform int zoffset;\n";

  shader += "uniform vec2 dataMin;\n";
  shader += "uniform vec2 dataSize;\n";
  shader += "uniform int tminz;\n";

  shader += "uniform int lod;\n";
  shader += "uniform vec3 dirFront;\n";
  shader += "uniform vec3 dirUp;\n";
  shader += "uniform vec3 dirRight;\n";

  shader += "uniform vec3 brickMin;\n";
  shader += "uniform vec3 brickMax;\n";

  shader += genTextureCoordinate();
  
  if (tearPresent) shader += TearShaderFactory::generateTear(crops);
  if (cropPresent) shader += CropShaderFactory::generateCropping(crops);
  if (glowPresent) shader += GlowShaderFactory::generateGlow(crops);  
  if (viewPresent) shader += BlendShaderFactory::generateBlend(crops);
  if (pathCropPresent) shader += PathShaderFactory::applyPathCrop();
  if (pathViewPresent) shader += PathShaderFactory::applyPathBlend();

  shader += "void main(void)\n";
  shader += "{\n";

  shader += "  vec3 texCoord = gl_TexCoord[0].xyz;\n";

  shader += "if (any(lessThan(texCoord,brickMin)) || any(greaterThan(texCoord, brickMax)))\n";
  shader += "  discard;\n";

  if (crops.count() > 0)
    {
      shader += "  vec3 otexCoord = texCoord;\n";
      shader += "  float feather = 1.0;\n";
    }
  else
    {
      if (pathCropPresent)
	shader += "  float feather = 1.0;\n";
      if (pathViewPresent)
	shader += "  vec3 otexCoord = texCoord;\n";
    }

  if (glowPresent)
    {
      shader += "  vec3 glowColor = glow(otexCoord);\n";
      shader += "  float glowMix = max(glowColor.r, max(glowColor.g, glowColor.b));\n";
      shader += "  if (glowMix > 0.05) discard;";
    }

  if (tearPresent)
    {
      shader += "vec4 tcf = dissect(texCoord);\n";
      shader += "texCoord = tcf.xyz;\n";
      shader += "feather *= tcf.w;\n";
    }
  if (cropPresent) shader += "feather *= crop(texCoord, true);\n";
  if (pathCropPresent) shader += "feather *= pathcrop(texCoord, true);\n";


  shader += "texCoord.x = 1.0 + float(tsizex-2)*(texCoord.x-dataMin.x)/dataSize.x;\n";
  shader += "texCoord.y = 1.0 + float(tsizey-2)*(texCoord.y-dataMin.y)/dataSize.y;\n";
  shader += "texCoord.z = 1.0 + (float(texCoord.z)-float(tminz))/float(lod);\n";

  shader += genVgx();

  shader += getNormal();

  if (bit16)
    {
      shader += "int h0 = int(65535.0*vg.x);\n";
      shader += "int h1 = h0 / 256;\n";
      shader += "h0 = int(mod(float(h0),256.0));\n";
      shader += "float fh0 = float(h0)/256.0;\n";
      shader += "float fh1 = float(h1)/256.0;\n";

      shader += QString("vg.xy = vec2(fh0, fh1*%1 + tfSet);\n").arg(1.0/Global::lutSize());
    }
  else
    {
      if (Global::use1D())
	shader += "  vg.y = tfSet;\n";
      else
	{
	  shader += QString("  vg.y = grad*%1;\n").arg(1.0/Global::lutSize());
	  
	  shader += "  vg.y += tfSet;\n";
	}
    }

  shader += "  gl_FragColor = texture2D(lutTex, vg.xy);\n";

  shader += genPeelShader(peel, peelType,
			  peelMin, peelMax, peelMix,
			  false);
  
  if (Global::emptySpaceSkip())
    {
      shader += "  gl_FragColor.rgba = mix(vec4(0.0,0.0,0.0,0.0), gl_FragColor.rgba, prunefeather.x);\n";
      if (PruneHandler::blend())
	shader += blendVolume();
      else
	shader += tagVolume();
    }

  if (tearPresent || cropPresent || pathCropPresent)
    shader += "  gl_FragColor.rgba = mix(gl_FragColor.rgba, vec4(0.0,0.0,0.0,0.0), feather);\n";

  if (viewPresent) shader += "blend(otexCoord, vg, gl_FragColor);\n";
  if (pathViewPresent) shader += "pathblend(otexCoord, vg, gl_FragColor);\n";

//------------------------------------
  shader += "gl_FragColor = 1.0-pow((vec4(1,1,1,1)-gl_FragColor),";
  shader += "vec4(lod,lod,lod,lod));\n";
//------------------------------------

  // --- modulate shadow by homogenity
  shader += QString("  gl_FragColor.rgba *= 1.0-smoothstep(0.0, float(%1), grad);\n").arg(shadowintensity);

  shader += "  if (gl_FragColor.a < 0.01)\n";
  shader += "	discard;\n";
  shader += "\n";
  shader += QString("  gl_FragColor.rgba *= vec4(%1, %2, %3, %4);\n").\
                                        arg(r).arg(g).arg(b).arg(maxrgb);

//  shader += "  gl_FragColor.r = clamp(gl_FragColor.r, 0.0, 1.0);\n";
//  shader += "  gl_FragColor.g = clamp(gl_FragColor.g, 0.0, 1.0);\n";
//  shader += "  gl_FragColor.b = clamp(gl_FragColor.b, 0.0, 1.0);\n";
//  shader += "  gl_FragColor.a = clamp(gl_FragColor.a, 0.0, 1.0);\n";

  shader += "}\n";

  return shader;
}