5
$\begingroup$

i am using blender to create optical settings for my work as an engineer in applied optics. I would like to create a lighting with simulates a display which projects a sinusoidal fringe pattern. I am really new to blender, just worked through the basics - tutorial and i would like to know if it is possible to create such a lighting, without creating like 1024 different planes by hand, and set the emission coefficient to sampled sinus-values.

I would like to just create on plane, and subdivide it into 1024 subplanes, but i cannot set the emission coefficient for this because it is still handled as one object inside blender.

Would be cool if someone can help me with an elegant solution to this.


I try to design an optical setup to measure objects from the industry. I need a certain number of cameras under the same illumination, the camera images should ideally have a maximum overlap of the illuminated object. This is why i use blender to check out different setups and positions for the cameras.

in short: I want to design the optical setup in blender, to reduce the "search-space" in the real world in terms of where to find the ideal positions for the cameras.

this is what the light source should look like

enter image description here

$\endgroup$
5
  • 2
    $\begingroup$ Could you illustrate what you are trying to achieve with some images? It is not very clear what you are aiming for $\endgroup$ Nov 16, 2018 at 13:42
  • 2
    $\begingroup$ Is this an orthographic projection? Do you need shadows to be cast? Depending on what you need, exactly, you might not need a light.. just appropriately projected textures. $\endgroup$ Nov 16, 2018 at 17:08
  • 2
    $\begingroup$ I'm not sure I completely understand your requirements here, but could you meet your needs by using an image texture of your sine pattern (or an appropriate Wave texture) as the input to the "strength" parameter of an Emission shader? Math node(s) (e.g. "Multiply" and/or "Add") between the texture and the Emission shader would let you adjust the overall illumination--or use a Color Ramp node for more control. $\endgroup$
    – risingfall
    Nov 16, 2018 at 17:40
  • $\begingroup$ @risingfall Based on what I understand from the post, this is probably the way to go, however the OP probably has no idea what you're talking about being new to blender and all. Perhaps you could expand your comment to an answer once the OP has provided more information. $\endgroup$ Nov 16, 2018 at 18:01
  • $\begingroup$ @Rey Leonard Amorato yes I would be happy to, I just didn't want to waste time on a fuller answer if I was off base as to what was being requested $\endgroup$
    – risingfall
    Nov 16, 2018 at 18:31

2 Answers 2

3
$\begingroup$

If I understand your requirement correctly, you're looking for a lamp that can project an undistorted (sinusoidal) banded image. This is very similar to Spot light with square shape and, in fact, you could potentially use the example provided there and simply use your image in the Image Texture to generate the required projection.

However, by taking the X coordinate and feeding that into a Sine maths node we can generate the sinusoidal illumination directly using the following nodes on the Point Lamp :

nodes

The Mapping node allows you to adjust the direction of the projection while the Value node controls the pitch of the banding. The 'Clip' frame simply limits the projection to the bounds -0.5 to 0.5 in each axis (so you get a clipped square projection) - adjust these values if you require a different aspect ratio or unbound projection. The 'Sine' frame simply generates the banding by multiplying by the 'frequency', adding 1.0 to remove negative values, and then multiplying by a constant for a suitable brightness for the lamp.

As in the linked question, the key to getting an undistorted projection is the Divide by the Z component of the Normal.

Here's the result :

result

Blend file included

$\endgroup$
0
1
$\begingroup$

Sine Gradient

I am not sure if I quite understand the requirement. But here is a simple script that sets the strength of the emission shader based on the sine value. See if this helps. The parameter names are self-explanatory. If you want a different color for negative f(x) values, just un-comment the commented lines.

import bpy
import bmesh
from math import ceil, pi, sin, radians

def createMaterial(color, strength, matName):
    mat = bpy.data.materials.get(matName)
    if(mat != None):
        bpy.data.materials.remove(mat)
    mat = bpy.data.materials.new(matName)
    mat.use_nodes = True
    tree = mat.node_tree
    defNode = tree.nodes.get("Diffuse BSDF")
    mat.node_tree.nodes.remove(defNode)
    defNode = tree.nodes.new("ShaderNodeEmission")
    defNode.inputs["Strength"].default_value = strength
    defNode.inputs["Color"].default_value = color
    tree.links.new(defNode.outputs[0], tree.nodes.get("Material Output").inputs[0])        
    return mat

def createPlane(w, h, location, name):
    bm = bmesh.new()
    v0 = bm.verts.new((-w/2, -h/2, 0))
    v1 = bm.verts.new((w/2, -h/2, 0))
    v2 = bm.verts.new((w/2, h/2, 0))
    v3 = bm.verts.new((-w/2, h/2, 0))
    bm.faces.new((v0, v1, v2, v3))
    me   = bpy.data.meshes.new(name)
    bm.to_mesh(me)
    bm.free()
    obj = bpy.data.objects.new(name, me)
    obj.location = location
    bpy.context.scene.objects.link(obj)
    return obj

numCycles = 40
numPlanes = 1024
phase = 180

w = .01
h = 5
maxStrength = 1.

planesPerCycle = ceil(numPlanes / numCycles)
planeStartX = w/2 - numPlanes * w / 2

bpy.context.scene.render.engine = 'CYCLES'
planeName = '_sine_plane'
matName = '_sine_mat'

posColor = [1, 1, 1, 1]
#negColor = [.8, 0, 0, 1]

mats = []
incr = 2 * pi / planesPerCycle

for i in range(0, planesPerCycle):
    angle = i * incr + radians(phase)
    mag = maxStrength * sin(angle)
    color = posColor
    #if(mag < 0):
        #color = negColor
        #mag *= -1
    mats.append(createMaterial(color, mag, matName + str(i)))

for i in range(0, numPlanes):
    x =  planeStartX + i * w
    location = (x, 0, 0) 
    plane = createPlane(w, h, location, planeName + str(i))
    matIdx = i % planesPerCycle 
    plane.data.materials.append(mats[matIdx])
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.